vector迭代器失效问题
迭代器失效是什么?
迭代器失效,是不能再去拿迭代器去访问vector中的元素,此时的迭代器指向的这块空间已经被释放了,也就是说此时的迭代器已经是野指针了。
insert 可能会导致迭代器失效
当vector数组开辟一段的空间之后,调用insert函数,向数组中插入一个值后,有可能会导致原来的空间不足,这时候,vector要进行深拷贝,就会开辟一个更大的空间,将原来空间上的数据拷贝到新开辟的空间上。但是此时你的迭代器还是指着旧空间上的一个位置,是一个野指针。所以这个迭代器就已经失效了。
迭代器失效insert是增容导致的失效,但是是可能失效。如果插入一个数据之后,原来的数组空间不进行增容,那么insert插入之后就不会失效。
所以,insert会导致迭代器增容,迭代增容有可能导致迭代器失效。主要取决于插入后vector是否增容
迭代器失效以后,我们就不能再次使用这个迭代器了,我们必须重新再次查找特定元素更新迭代器。
如下列程序:
int main()
{
int a[] = {1,2,3,4};
vector<int> v (a,a + sizeof(a)/sizeof(int));
//指针是天然的迭代器,可以像迭代器一样使用
vector<int>::iterator pos = find(v.begin(),v.end(),3); //
// 或者这样写, auto pos = find(v.begin(),v.end(),3);
v.insert(pos,30); //有可能导致扩容,迭代器失效
cout << *pos << endl; //error, 访问野指针
}
erase会导致迭代器失效
erase使迭代器失效的原理
迭代器指向一个元素后,vector调用erase后,迭代器指向的这个元素被覆盖了。所以此时的迭代器在编译器环境下被认为错误。因为数组vector中没有这个被覆盖的元素了,数组中没有想要的那个元素了,所以迭代器就已经失效了。
所以,erase失效主要是指这个位置的值已将改变了,含义已经改变了
vs下的stl是pj版本的,自己加了检查,所以下面的程序就会崩溃。
int main()
{
vector<int> v = {1,2,3,4};
vector<int>::iterator pos = find(v.begin(),v.end(),3);
v.erase(pos);
cout << *pos << endl; //vs下会报错(pj版本加的检查), linux下不报错
}
总结: 迭代器pos指向的是3这个元素,erase调用之后3这个值就被覆盖掉了。含义已经改变了,所以vs下,禁止在访问这个迭代器pos了。