快捷搜索: 王者荣耀 脱发

deque 迭代器失效的问题详解

今天在看STL源码的时候,无意写了如下的代码,发现程序崩溃了:

<span style="font-size:14px;">    deque<int>::iterator iter=d.begin();
    d.insert(iter,5); 
    d.insert(iter,6); //崩溃,迭代器失效了

</span>
之前一直没有留意这个问题,后来结合源码和查找资料,得到如下的结论:

插入操作:

1、在队前或队后插入元素时(push_back(),push_front()),由于可能缓冲区的空间不够,需要增加map中控器,而中控器的个数也不够,所以新开辟更大的空间来容纳中控器,所以可能会使迭代器失效;但指针、引用仍有效,因为缓冲区已有的元素没有重新分配内存。

2、在队列其他位置插入元素时,由于会造成缓冲区的一些元素的移动(源码中执行copy()来移动数据),所以肯定会造成迭代器的失效;并且指针、引用都会失效。

删除操作:

1、删除队头或队尾的元素时,由于只是对当前的元素进行操作,所以其他元素的迭代器不会受到影响,所以一定不会失效,而且指针和引用也都不会失效;

2、删除其他位置的元素时,也会造成元素的移动,所以其他元素的迭代器、指针和引用都会失效。

测试代码:

deque<int>::iterator iter=d.begin();
d.push_back(10);
cout<<*iter<<endl;
在vs2012中运行时,程序立即崩溃:

而且,不管有没有出现重新分配map中控器,往deque中插入元素都会导致迭代器的失效,所以,插入一个元素后,iter迭代器已经失效了,所以再对失效的迭代器取值会导致程序崩溃,出现如上错误,不知道其他的编译器对这种情况是如何处理的。

查找资料为:

vector迭代器的几种失效的情况: 1.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。 2.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。 3.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。

deque迭代器的失效情况: ,在C++Primer一书中是这样限定的, 1.在deque容器首部或者尾部插入元素不会使得任何迭代器失效。//通过vs2012测试不管前端插入还是后端插入,都会使迭代器 失效 2.在其首部或尾部删除元素则只会使指向被删除元素的迭代器失效。 3.在deque容器的任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器失效。

再次测试:

deque<int>::iterator iter=d.begin();
d.pop_back();
cout<<*iter<<endl;
上面代码可以顺利通过测试,说明队尾弹出元素并不会使迭代器失效(当然删除的那个元素的迭代器肯定会失效)。
所以,为了避免程序因为迭代器的失效而程序崩溃,所以尤其在对元素进行插入和删除的操作时一定要考虑迭代器的失效问题,上面第一个测试代码的正确版如下:
int main()
{
	int i[10]={1,2,5,3,7,5,2,8,5,9};
	list<int>  l;
	deque<int,allocator<int>> d(i,i+10);
	deque<int>::iterator iter=d.begin();
	iter=d.insert(iter,5);   //插入返回一个插入点的迭代器,重新给iter迭代器赋值就没有问题了。
	iter=d.insert(iter,6);
	cout<<*iter<<endl;  //输出结果为6
}



经验分享 程序员 微信小程序 职场和发展