在C++;11 C++中最流行的帖子声称,过去的迭代器(即,由代码返回的)(或代码> >, cEd()(, r>(),>代码> >和代码> >(代码>),不清楚是否按照与正常迭代器相同的规则,这是指向容器中的元素的。这些声明,为2003和2011 C++,推迟后讨论,其中公认的答案表明,2003标准是含糊不清的问题。这一结论是基于23.1/10(在swap()的上下文中)中的一条评论得出的,该评论似乎暗示,当规范没有明确提到结束迭代器失效时,它们可能会失效

在C++;11 C++中最流行的帖子声称,过去的迭代器(即,由代码返回的)(或代码> >, cEd()(, r>(),>代码> >和代码> >(代码>),不清楚是否按照与正常迭代器相同的规则,这是指向容器中的元素的。这些声明,为2003和2011 C++,推迟后讨论,其中公认的答案表明,2003标准是含糊不清的问题。这一结论是基于23.1/10(在swap()的上下文中)中的一条评论得出的,该评论似乎暗示,当规范没有明确提到结束迭代器失效时,它们可能会失效,c++,iterator,C++,Iterator,mike seymour对该帖子问题的评论表明C++11在这个问题上是明确的,在deques的情况下。我的问题是关于所有容器: 在C++11中,是否有任何容器操作会使结束迭代器失效,以及这种行为在语言规范中是不明确的 换言之 在执行了一个容器操作(该操作不会使过去的结束迭代器无效)之后,我可以相信过去的结束迭代器的有效性吗 如果标准规定该操作不会使迭代器失效,那么您应该能够信任它。在标准库实现中,任何其他内容都应视为bug 我的问题是关于所有容器: 在C++11中,是否有任何容器操作可能

mike seymour对该帖子问题的评论表明C++11在这个问题上是明确的,在
deque
s的情况下。我的问题是关于所有容器:

  • 在C++11中,是否有任何容器操作会使结束迭代器失效,以及这种行为在语言规范中是不明确的
换言之

  • 在执行了一个容器操作(该操作不会使过去的结束迭代器无效)之后,我可以相信过去的结束迭代器的有效性吗

如果标准规定该操作不会使迭代器失效,那么您应该能够信任它。在标准库实现中,任何其他内容都应视为bug

我的问题是关于所有容器:

  • 在C++11中,是否有任何容器操作可能使结束迭代器之后的循环无效,以及在 语言规范
我不确定你所说的“在语言规范中,这种行为是不明确的”是什么意思,但肯定有一些操作通过结束运算符(比如插入到
std::vector
std::string
)而失效

换言之

  • 在执行了一个容器操作(该操作没有说它可能会失效)之后,我可以信任一个过期迭代器的有效性吗 过去的结束迭代器

您可以像信任任何其他迭代器一样信任结束迭代器:任何不会(潜在地)使迭代器无效的操作都不会使迭代器无效。除了可能的标准运动一个错误,这是所有的操作,它没有说,他们(潜在)无效的运营商

至少在GCC端迭代器中,std::map的迭代器无效:

#include <set>
#include <stdlib.h>
#include <assert.h>
int main() {
  std::set<int> a;
  a.insert(1);
  std::set<int>::reverse_iterator rit(a.rbegin());
  ++rit;
  assert(rit==a.rend());
  a.erase(a.begin());
  assert(a.rend()==rit); // FAIL
}
#包括
#包括
#包括
int main(){
std::设置a;
a、 插入(1);
std::set::reverse_迭代器rit(a.rbegin());
++rit;
断言(rit==a.rend());
a、 删除(a.begin());
断言(a.rend()==rit);//失败
}

在执行不会使任何迭代器无效的操作后,您可以信任结束迭代器的有效性。对于所有其他情况,我不知道,我真的不在乎:重新获取迭代器(这是一个常数时间操作),并且不需要担心特定迭代器是否无效……当然,有些操作可能会使结束迭代器无效<代码>向量::擦除,例如,“在擦除点或之后使迭代器和引用无效。”结束迭代器必须是“在擦除点之后”。@dribeas:感谢您的解决方法;我确信它在几乎所有情况下都是最佳的,特别是考虑到编译器内联等等。有传闻()表明,缓存过去的结束指针可能会获得性能优势;的确,这激发了我的问题。@JamesMcNellis:同意。这里的标准是明确的,因为结束迭代器[定义在某处]在擦除点之后。关于
vector::reserve()
,23.3.6.3/5(我有版本n3337),“重新分配使引用序列中元素的所有…迭代器无效”,这个列表不包括过去的结束迭代器,根据定义,它不指向序列中的元素。然而,SGI实现使所有迭代器失效,可能是过去的迭代器也失效了[。更多:这肯定是C++11规范中的一个缺陷。我个人同意我(第二个)的否定答案这个问题应该意味着标准中有一个错误。我同意你的回答,但我真的希望你能证明你所说的相反是错误的。也就是说,“你应该能够相信,如果标准没有说明迭代器是无效的,那么容器操作不会使任何迭代器(包括过期的迭代器)无效。”e对于问题注释中的保留:
“重新分配使引用序列中元素的所有…迭代器无效,”
?你会说这肯定是标准中的一个缺陷吗?@Mark:可能是。常识告诉我们,对于许多容器,使序列中的迭代器无效也必然使最终迭代器无效。(但是,我离一个高律师的C++用户的语言律师来说是很远的,所以要带着一点盐。)有趣的,但是有瑕疵。<代码>。()(代码)>返回一个迭代器适配器。具体地,一个适应<代码> Ac新()(代码)>,而不是<代码> AN()(代码)>,所以没有矛盾。<代码> rand()根据定义调整
begin()
,该迭代器被
erase
显式地无效。反例说明这一点:。对于常规迭代器,甚至在删除单个元素的情况下也是如此:就像原始示例一样