C++迭代器失效问题(insert、erase)
什么是迭代器
迭代器提供了一种方法,使它能够按照顺序访问某个容器所含的各个元素,但无需暴露该容器的内部结构,换句话说迭代器就是指针的简单包装,通过一个模板类封装的对象
迭代器的失效问题
一、迭代器在vector、deque等内存连续的容器删除中失效
对于序列式容器,比如vector,删除当前的iterator会使后面所有元素的iterator都失效。这是因为顺序容器内存是连续分配(分配一个数组作为内存),删除一个元素导致后面所有的元素会向前移动一个位置。(删除了一个元素,该元素后面的所有元素都要挪位置,所以,iter++,已经指向的是未知内存)。
二、迭代器在map\set\mutilset等关联类的容器中删除不失效
在关联类容器(map\set\mutilset)删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前iterator即可。这是因为map之类的容器,使用了红黑树来实现,插入、删除一个结点不会对其他结点造成影响。erase迭代器只是被删元素的迭代器失效,但是返回值为void,所以要采用erase(iter++)的方式删除迭代器。
三、迭代器在内存连续的容器中插入元素,插入位置之前的迭代器有效,之后的迭代器失效;内存非连续得容器插入迭代器不失效
insert插入没有返回值,因此insert不能在循环中 连续的 进行插入操作(插入位置之后的迭代器失效,无法遍历)
注意: 正常使用erase删除迭代器是有返回值的,返回的是下一个有效的迭代器,
#include<iostream> #include<thread> #include<string> #include<vector> #include<list> #include<mutex> #include<future> using namespace std; int main() { std::vector<int>v{ 0, 1, 2, 3 }; for (auto i = v.begin(); i != v.end(); i++) { //cout << *i << endl; i=v.erase(i);//迭代器i被删除之后是一个无效的迭代器(nullptr指针),因此不能对i进行任何操作; //erase()返回值指向下一个迭代器 cout << *i << endl; } system("pause"); return 0; }
vector::const_iterator 和 const vector::iterator的区别
前者不能修改容器中的元素,如:*newiter=11 属于错误,可以修改迭代器自身,如:newiter++正确;后者可以修改指向容器的元素,如:*newiter=11正确,迭代器本身不能被修改,如:newiter++错误;