C ++ 11中的过去迭代器失效

时间:2012-07-05 18:35:38

标签: c++ iterator

关于C ++ Iterator invalidation rules的最受欢迎的帖子声称不清楚过去的结束迭代器(即end()cend()rend()返回的迭代器,和crend())根据与普通迭代器相同的规则无效,这些迭代器指向容器中的元素。这些针对2003年和2011年C ++的声明,推迟到讨论End iterator invalidation rules的帖子,其中接受的答案表明2003标准在这个问题上是模棱两可的。这个结论基于23.1 / 10中的注释(在swap()的上下文中)似乎意味着当规范没有明确提到过去的迭代器失效时,它们可能会失效。

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

  • 在C ++ 11中,是否有任何容器操作可能使过去的迭代器无效,并且在语言规范中这种行为是不明确的?

不同地说,

  • 在执行容器操作后,我是否可以信任过去的迭代器的有效性,而不会说它可能会使过去的迭代器无效?

3 个答案:

答案 0 :(得分:11)

  

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

     
      
  • 在C ++ 11中,是否有任何容器操作可能使过去的迭代器无效,并且这种行为在这里是不明确的   语言规范?
  •   

我不确定你对“语言规范中这种行为模糊不清”的意思,但肯定有一些操作会使过去的操作符无效(比如插入std::vector或{{1 }})。

  

不同地说,

     
      
  • 执行容器操作后,我是否可以信任过去的迭代器的有效性,但不会说它可能会失效   过去的结束迭代器?
  •   

您可以像任何其他迭代器一样信任过去的迭代器:任何不会(可能)使迭代器失效的操作都不会使它们失效。除了标准运行错误的可能性之外,所有操作都没有说它们(可能)使运营商无效。

答案 1 :(得分:2)

如果标准说操作不会使迭代器无效,那么你应该能够信任它。其他任何东西都应该被视为标准库实现中的错误。

答案 2 :(得分:0)

至少在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
}