【发布时间】:2012-07-06 05:15:23
【问题描述】:
C++ 上最受欢迎的帖子Iterator invalidation rules 声称不清楚过去的迭代器(即由end()、cend()、rend() 和crend() 返回的迭代器)是否无效根据与普通迭代器相同的规则,它们指向容器中的元素。这些声明适用于 2003 年和 2011 年 C++,请参阅讨论 End iterator invalidation rules 的帖子,其中公认的答案表明 2003 年标准在此问题上含糊不清。这个结论是基于 23.1/10 中的评论(在swap() 的上下文中),这似乎暗示当规范没有明确提到过去迭代器的失效时,它们可能会失效。
对该帖子问题的评论(由 mike-seymour 撰写)表明 C++11 在这个问题上是明确的,在 deques 的情况下。我的问题是关于所有容器的:
- 在 C++11 中,是否有任何容器操作可能使过去的迭代器无效,并且这种行为在语言规范中是不明确的?
换个说法,
- 在执行容器操作后,我是否可以相信过去迭代器的有效性,但该操作并未说明它可能会使过去的迭代器失效?
【问题讨论】:
-
在执行不会使任何迭代器失效的操作后,您可以信任过去迭代器的有效性。对于所有其他情况,我不知道,我真的不在乎:重新获取迭代器(这是一个恒定时间操作)并且无需担心该特定迭代器是否无效......
-
肯定有一些操作可能使结束迭代器无效。
vector::erase,例如,“在擦除点或之后使迭代器和引用无效。”结束迭代器必须在“擦除点之后”。 -
@dribeas:感谢您的解决方法;我确信它在几乎所有情况下都是最佳的,尤其是考虑到编译器内联等。有轶事证据 (stackoverflow.com/q/3084109/985943) 表明您可能会从缓存过去的指针中获得性能优势;确实这激发了我的问题。
-
@JamesMcNellis:同意。这里的标准是明确的,因为结束迭代器是在擦除点之后[定义在某处]。
vector::reserve(), 23.3.6.3/5(我有 rev. n3337)怎么样,“重新分配使所有引用序列中元素的...迭代器无效”,这个列表不包括过去的迭代器,根据定义,它不指向序列中的元素。然而,SGI 实现使 all 迭代器失效,大概也是过去的迭代器 [sgi.com/tech/stl/Vector.html#5].更多:stackoverflow.com/a/1624961/985943 -
这肯定是 C++11 规范中的一个缺陷。