vector迭代器失效未崩溃却输出正常?C++代码运行疑惑求解
为什么vector erase后迭代器失效却没崩溃?
你遇到的这个情况其实是**未定义行为(Undefined Behavior)**的典型表现——C++标准不保证这种代码一定会崩溃,只是说它的行为完全不可预测,这次碰巧得到了“正确”的输出,纯属巧合。
先看你第一段有问题的代码:
int main() { vector<int> v; v.reserve(10); for(int i=0;i<10;i++) v.push_back(i); for(vector<int>::const_iterator iter=v.begin();iter!=v.end();iter++) { if(*iter==5) v.erase(iter); } for(vector<int>::const_iterator iter=v.begin();iter!=v.end();iter++) cout<<*iter<<endl; return 0; }
根据C++标准,当你调用v.erase(iter)时,被删除元素的迭代器(也就是这里的iter)以及所有指向该元素之后位置的迭代器都会失效。但你的代码在erase之后,仍然执行了iter++——这一步操作的行为是标准完全不做保证的:
- 在某些编译器/平台上,这可能直接导致程序崩溃(比如访问非法内存);
- 在你当前使用的环境里,vector的迭代器本质是原生指针,erase后后续元素会向前移动一位,失效的
iter刚好指向了原来下一个元素的新位置,iter++之后碰巧还能继续遍历到正确的终点,所以看起来输出是对的。
但千万不要依赖这种“巧合”!换个编译器、换个vector元素类型,或者调整遍历逻辑,程序随时可能崩溃或者输出错误结果。
你给出的正确写法才是完全符合标准的:
for(vector<int>::const_iterator iter=v.begin();iter!=v.end();) { if(*iter==5) iter=v.erase(iter); else iter++; }
这里的关键是:vector::erase()会返回一个指向被删除元素的下一个有效元素的迭代器。所以当我们删除元素时,直接用这个返回值更新iter,就能避免使用失效的迭代器;而不需要删除时,再正常递增iter,这样整个遍历过程的行为是完全可预测的。
我当初啃《C++ Primer》的时候也踩过这个坑,记住:未定义行为不是“一定会坏”,而是“可能任何时候坏”,写代码必须严格遵循标准规则,不能依赖偶然的运行结果。
内容的提问来源于stack exchange,提问作者Howo
相关产品推荐
相关产品推荐

