检验vector::iterator在push了N元素后的有效性

cxjddd 2003-06-11 04:00:59
对于那些iterator会不会失效、会在什么时候失效一直不太明白。于是就想自己验证一下。第一个动手的是vector的iterator。
  我的方法是:
  先push一个0,记录begin()值和begin()元素的值。
  然后,从1开始push,使vector一定要重新分配内存。这样没有两个元素相等。
  再就开始比较:从begin()到end(),找是否有与原来的begin()相等并且也指向0的。如果有,表示原来的iterator有效;没有,则原来的iterator已经失效了。
  我测试的结果是“失效”。
  不知我的方法对不对。我想是很不完善的。

  我想得到完整的关于iterator的“时效性”问题的答案。请各位说说吧。

#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;

int main ()
{
vector<int> vec;
vec.push_back (0);
vector<int>::const_iterator ivec1 = vec.begin();
int i1 = *ivec1;

int l = vec.capacity () * 2 + 1;
for (int i=0; i<l; i++)
vec.push_back (i+1);

vector<int>::const_iterator ivec=vec.begin(), e=vec.end();
for (; ivec != e; ++ivec)
if ((ivec1 == ivec) && (i1 = *ivec))
{
cout << "OK! The old iterator of vector is in effect!" << endl;
break;
}
if (ivec == e)
{
cout << "The old iterator of vector is nullity!" << endl;
}

system ("Pause");
return 0;
}
...全文
100 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
fingster 2003-06-11
  • 打赏
  • 举报
回复
楼上说的没错。
当vector内存重新分配的时候iterator就失效。
短歌如风 2003-06-11
  • 打赏
  • 举报
回复
vector不保证在添加元素后原迭代器的有效性,如果你需要这种保证,使用list。deque的保证比vector强一些。
或者另写一个具有安全一些的迭代器的vector,迭代器不保存指针,而是保存vector的引用和索引号,把用指针访问改为用vector::operator[]去访问,不过效率上会有影响。
boxban 2003-06-11
  • 打赏
  • 举报
回复
The semantics of iterator invalidation for deque is as follows. Insert (including push_front and push_back) invalidates all iterators that refer to a deque. Erase in the middle of a deque invalidates all iterators that refer to the deque. Erase at the beginning or end of a deque (including pop_front and
pop_back) invalidates an iterator only if it points to the erased element.


A vector's iterators are invalidated when its memory is reallocated. Additionally, inserting or deleting an element in the middle of a vector invalidates all iterators that point to elements following the insertion or deletion point. It follows that you can prevent a vector's iterators from being invalidated if you use reserve() to preallocate as much memory as the vector will ever use, and if all insertions and deletions are at the vector's end.

A list is a doubly linked list. That is, it is a Sequence that supports both forward and backward traversal, and (amortized) constant time insertion and removal of elements at the beginning or the end, or in the middle. Lists have the important property that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates only the iterators that point to the elements that are removed. The ordering of iterators may be changed (that is, list<T>::iterator might have a different predecessor or successor after a list operation than it did before), but the iterators themselves will not be invalidated or made to point to different elements unless that invalidation or mutation is explicit.

A slist is a singly linked list: a list where each element is linked to the next element, but not to the previous element. That is, it is a Sequence that supports forward but not backward traversal, and (amortized) constant time insertion and removal of elements. Slists, like lists, have the important property that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates only the iterators that point to the elements that are removed. The ordering of iterators may be changed (that is, slist<T>::iterator might have a different predecessor or successor after a list operation than it did before), but the iterators themselves will not be invalidated or made to point to different elements unless that invalidation or mutation is explicit.


A bit_vector's iterators are invalidated when its memory is reallocated. Additionally, inserting or deleting a bit in the middle of a bit_vector invalidates all iterators that point to bits following the insertion or deletion point. It follows that you can prevent a bit_vector's iterators from being invalidated if you use reserve() to preallocate as much storage as the bit_vector will ever use, and if all insertions and deletions are at the bit_vector's end.

Set/multiset/hash_set/hash_multiset has the important property that inserting a new element into a set does not invalidate iterators that point to existing elements. Erasing an element from a set also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being erased.

Map/multimap/hash_map/hash_multimap has the important property that inserting a new element into a map does not invalidate iterators that point to existing elements. Erasing an element from a map also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being erased.


A stack is an adaptor that provides a restricted subset of Container functionality: it provides insertion, removal, and inspection of the element at the top of the stack. Stack is a "last in first out" (LIFO) data structure: the element at the top of a stack is the one that was most recently added. Stack does not allow iteration through its elements.
Stack is a container adaptor, meaning that it is implemented on top of some underlying container type.By default that underlying type is deque, but a different type may be selected explicitly.


A queue is an adaptor that provides a restricted subset of Container functionality. A queue is a "first in first out" (FIFO) data structure. That is, elements are added to the back of the queue and may be removed from the front; Q.front() is the element that was added to the queue least recently. Queue does not allow iteration through its elements.
Queue is a container adaptor, meaning that it is implemented on top of some underlying container type. By default that underlying type is deque, but a different type may be selected explicitly.

A priority_queue is an adaptor that provides a restricted subset of Container functionality: it provides insertion of elements, and inspection and removal of the top element. It is guaranteed that the top element is the largest element in the priority_queue, where the function object Compare is used for comparisons. Priority_queue does not allow iteration through its elements.
Priority_queue is a container adaptor, meaning that it is implemented on top of some underlying container type. By default that underlying type is vector, but a different type may be selected explicitly.

cxjddd 2003-06-11
  • 打赏
  • 举报
回复
我也是认为当需要从新分配内存的时候,以前的iterator会失效。所以,最好用reserve来预定大小,这样就可以确定在某个范围里不会让iterator失效了。
chinazcw 2003-06-11
  • 打赏
  • 举报
回复
是失效了,学艺为精,说不出为什么?
GaoYakun 2003-06-11
  • 打赏
  • 举报
回复
最好的办法是读stl源码和stl标准。
fangrk 2003-06-11
  • 打赏
  • 举报
回复
当size()==capacity()并且添加元素的时候,iterator失效
cxjddd 2003-06-11
  • 打赏
  • 举报
回复
汗!出错了!程序中第一个if应该是i1 == *ivec。
幸好对vector没有什么关系。请大家注意了。

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧