为什么vector :: pop_back使迭代器无效(end() - 1)?

Meh*_*dad 6 c++ iterator invalidation

注意:这个问题也适用于erase.见底部.


end() - 1pop_back调用a 之后迭代器失效的原因是vector什么?

澄清一下,我指的是这种情况:

std::vector<int> v;
v.push_back(1);
v.push_back(2);

std::vector<int>::iterator i1 = v.begin(), i2 = v.end() - 1, i3 = v.begin() + 1;

v.pop_back();

// i1 is still valid
// i2 is now invalid
// i3 is now invalid too

std::vector<int>::iterator i4 = v.end();

assert(i2 == i4);  // undefined behavior (but why should it be?!)
assert(i3 == i4);  // undefined behavior (but why should it be?!)
Run Code Online (Sandbox Code Playgroud)

为什么会这样?(即这种失效何时会证明对实施有益?)

(请注意,这不仅仅是一个理论问题.如果您尝试在调试模式下执行此操作,那么Visual C++ 2013 - 也可能是2012年 - 如果您已_ITERATOR_DEBUG_LEVEL设置为,则显示错误2.)


关于erase:

请注意,同样的问题适用于erase:
为什么erase(end() - 1, end())无效end() - 1

(所以请不要说," 因为它等同于呼叫而pop_back失效"end() - 1erase(end() - 1, end()) ;这只是提出问题.)

Dav*_*eas 2

有趣的问题实际上是迭代器失效意味着什么。我确实没有从标准中得到好的答案。我所知道的是,在某种程度上,该标准并不将迭代器视为指向容器内某个位置的指针,而是将其视为容器内特定元素的代理。

考虑到这一点,在擦除向量中间的单个元素后,删除点之后的所有迭代器都会变得无效,因为它们不再引用之前引用的同一元素。

对这条推理的支持来自于容器中其他操作的迭代器失效子句。例如, on insert,标准保证如果没有重新分配,插入点之前的迭代器仍然有效。异常情况下的异常规则,它使插入点之后的所有迭代器无效。

如果迭代器的有效性仅与迭代器指向的容器中存在一个元素这一事实相关,那么该操作不会使任何迭代器失效(同样,在没有重新分配的情况下)

更进一步地,如果您将迭代器有效性视为指针有效性,那么在操作期间,向量中的任何迭代器都不会失效erase。迭代end()-1器将变得不可取消引用,但它可以保持有效,但情况并非如此。