参考两篇文章:https://blog.csdn.net/skyroben/article/details/70877008
https://lichanghao.github.io/2016/08/01/C++%E4%B8%ADiterator%E5%A4%B1%E6%95%88%E7%9A%84%E9%97%AE%E9%A2%98/
迭代器是一种面向对象的广义指针,用于指向容器中或流中的对象。可以看做是一种指向数据的指针。
失效举例:
删除vector容器中的偶数
代码:
#include <iostream> #include <vector> using namespace std; void Printvector(vector<int> &l) { vector<int>::iterator it = l.begin(); while (it != l.end()) { if (*it % 2 == 0) { //l.erase(it); //(1) 1 输出之后崩溃 //it=l.erase(it); //(2) 1 3 5 输出之后崩溃 } cout << *it << " "; ++it; } cout << endl; } void Testvector() { vector<int> l; l.push_back(1); l.push_back(2); l.push_back(3); l.push_back(4); l.push_back(5); l.push_back(6); Printvector(l); } int main() { Testvector(); return 0; }
(1)程序输出1之后就崩溃的原因:
通过调试观察现象:
作者解释:明显可以看到使用erase删除某一个结点之后,vector迭代器虽然还是指向当前位置,而且也引起了元素前挪,但是由于删除结点的迭代器就已经失效,指向删除点后面的元素的迭代器也全部失效,所以不能对当前迭代器进行任何操作;需要对迭代器重新赋值或者接收erase它的返回值;
个人理解:迭代器类似于一个指针,指向数据为2的节点时数据被删除,而且没有给迭代器重新赋值,那么此时此迭代器的指向不明确,输出该迭代器位置及后边位置的数据会造成程序崩溃。
那么,如果给进行重新赋值
作者解释:使用it接收erase的返回值,假如vector最后一个元素为奇数按照(2)的方式运行程序是不会崩溃的,这里崩溃的原因就好像数组访问越界,因为元素6已经被删除,不属于vector(数组)了,而你还继续对指向它的指针解引用,所以程序崩溃。
个人理解:对it重新赋值后,遍历到6的位置时不会崩溃,但因为删除6节点后没有重新赋值,造成崩溃。
STL中erase实现的源代码:
iterator erase(iterator position) { if (position + 1 != end()) copy(position + 1, finish, position); --finish; destroy(finish); return position; }
(3)正确的使用方式
void Printvector(vector<int> &l) { vector<int>::iterator it = l.begin(); while (it != l.end()) { if (*it % 2 == 0) { it = l.erase(it); } else { cout << *it << " "; ++it; } } cout << endl; }
即只有在it指向明确的时候才进行输出,否则不输出