调用擦除后迭代器无效

时间:2012-02-16 11:12:06

标签: c++ stl

我有点困惑。我学到或被告知的是,如果调用erase,向量的迭代器将变为无效。但为什么以下代码有效。它使用g ++编译并在Linux中运行。

#include <vector>
#include <iostream>

using namespace std;

int main() {
  vector<int> vec;
  vec.push_back(1);
  vec.push_back(2);
  vec.push_back(3);

  vector<int>::iterator it = vec.begin();
  ++it;
  vector<int>::iterator it2;

  it2 = vec.erase(it);
  cout << "it: " << *it << endl;
  cout << "it2: " << *it2 << endl;
}

感谢您的任何反馈!

3 个答案:

答案 0 :(得分:2)

来自http://www.cplusplus.com/reference/stl/vector/erase/(不是世界上最好的C ++参考):

  

这会使所有迭代器和对位置(或第一个)及其后续元素的引用无效。

所以it无效;使用它会导致未定义的行为。事实上,你碰巧得到了你所期望的纯粹的坏运气。

答案 1 :(得分:1)

您正在做的是未定义的行为,并且它“工作”完全是偶然的。你不能也绝不能永远依赖于此,因为它可以做任何事情。它的行为没有定义。

答案 2 :(得分:0)

作为实施细节,vector<int>::iterator可以很容易地int*。我认为在g++中它是int*周围的一个非常薄的包装器。如果是这种情况,那么删除三元素向量的中间元素意味着it的指针数据成员指向与删除的元素相同的地址,这当然将包含以前在它之后的值,并且it2也有效地引用了该值。

标准并不保证it仍会引用任何内容,这就是为什么您不能依赖于此处观察到的行为的原因。但它解释了你所看到的。当你取消引用it时,一个实现几乎不得不做出任何其他事情。但编译器确实每天都在不遗余力:例如调试库的版本,而一些优化技术依赖于假设你的代码是正确的。