调用擦除后迭代器无效
我有点困惑。我了解到或被告知的是,如果调用擦除,向量的迭代器将变得无效。但为什么下面的代码有效。它使用 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;
}
感谢您的任何反馈!
I am confused a bit. What I have learned or been told is that an iterator of a vector becomes invalid if erase is called. But why the code below works. It is compiled using g++ and run in 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;
}
Thanks for any feedbacks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
来自 http://www.cplusplus.com/reference/stl/vector/erase/< /a> (不是世界上最好的 C++ 参考):
所以
它
是无效的;使用它会导致未定义的行为。事实上,你碰巧得到了你所期望的东西,这纯粹是运气不好。From http://www.cplusplus.com/reference/stl/vector/erase/ (not the world's best C++ reference):
So
it
is invalid; using it results in undefined behaviour. The fact that you happen to get what you expect is pure bad luck.你正在做的是未定义的行为,并且它“有效”完全是偶然的。您不能也决不能永远依赖它,因为它几乎可以做任何事情。它的行为没有定义。
What you're doing is Undefined Behaviour, and that it "works" is entirely accidental. You cannot and must not ever rely on this, because it could do just about anything. The behaviour of it is not defined.
作为实现细节,
vector::iterator
很容易是int*
。我认为在g++
中,它是一个围绕int*
的非常薄的包装器。如果是这种情况,那么擦除三元素向量的中间元素意味着it
的指针数据成员仍指向与删除的元素相同的地址,当然该地址将包含该值之前紧随其后,并且也被it2
有效引用。该标准不保证
it
仍会引用任何内容,这就是为什么您不能依赖在这里观察到的行为。但它解释了你所看到的。当您取消引用它
时,实现几乎必须竭尽全力才能使其他事情发生。但编译器每天都会不遗余力:例如,调试库的版本,并且一些优化技术依赖于代码正确的假设。As an implementation detail,
vector<int>::iterator
can easily beint*
. I think ing++
it's a very thin wrapper around anint*
. If that's the case, then erasing the middle element of a three-element vector means that the pointer data member ofit
is left pointing at the same address as the element removed, which of course will contain the value that previously was straight after it, and which is also validly referred to byit2
.The standard does not guarantee that
it
will still refer to anything, which is why you can't rely on the behavior you've observed here. But it explains what you've seen. An implementation pretty much has to go out of its way to make anything else happen when you dereferenceit
. But compilers do go out of their way every day: debugging versions of the libraries for example, and some optimization techniques rely on assumptions that your code is correct.