下面我们来讲一讲迭代器失效的问题。
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用了一块已经被释放的空间,造成的后果就是程序崩溃。
对于vector来说,可能会导致迭代器失效的操作有:
1.会引起底层空间改变的操作,都有可能是迭代器失效。
比如:resize,reserve,insert,assign,push_back。
下面我们先举一个简单的例子。
int main()
{vector<int> tmp = { 1,2,3,4,5,6 };//it是扩容之前的迭代器auto it = tmp.begin();//现在对tmp进行扩容tmp.assign(100, 8);//现在已经扩容,it还是指向的旧空间//一段已经被释放过的空间//这个时候再用迭代器遍历tmp,程序就会崩溃while (it != tmp.end()){cout << *it << " ";it++;}cout << endl;return 0;
}
不管怎样,如果说我们进行插入操作的时候,如果引起了扩容,也会导致迭代器失效。
我们在操作的时候一定要注意这一特点。
2.指定元素的删除操作-erase
int main()
{vector<int> tmp = { 1,2,3,4,5,6,7,8 };//现在我们来使用迭代器将tmp中的偶数删除auto it = tmp.begin();while (it != tmp.end()){if (*it % 2 == 0){tmp.erase(it);}else{it++;}}for (auto cur : tmp){cout << cur << " ";}cout << endl;return 0;
}
乍一看,这一串代码好像没有任何问题,但是运行起来,程序就会崩溃。
这是erase删除元素后,该位置后面的所有元素都会向前移动,没有导致底层空间的改变,理论上讲迭代器不会失效,但是,如果我们再删最后一个元素的时候,删完it就会移动到end()去,而end是没有元素的,所以就导致越界访问,程序崩溃。
所以这段代码的正确形式就是我们在删除一个元素的时候,再接受它的返回值,因为erase删除过后,会返回一个值,它会指向被删除元素的下一位。
总结
迭代器失效的解决办法就是:在使用前,对迭代器重新赋值就行了。