什么是迭代器失效?

时间:2013-06-03 19:32:57

标签: c++ iterator

我看到它引用了很多,但没有明确答案它到底是什么。我的经验是使用更高级别的语言,所以我不熟悉集合框架中存在无效性。

什么是迭代器失效?

为什么会出现?为什么难以处理?

3 个答案:

答案 0 :(得分:37)

  1. 迭代器是美化的指针。迭代器失效很像指针失效;这意味着它突然指向垃圾数据。

  2. 因为这样做是非常自然但错误的:

    for(iterator it = map.begin(); it != map.end(); ++it) {
        map.erase(it->first);
        // whoops, now map has been restructured and iterator 
        // still thinks itself is healthy
    }
    
  3. 因为那个错误就在那儿?没有编译器错误,没有警告,你输了。你只需要训练得足以观察它们并防止它们。如果你不知道你在做什么,那就是非常阴险的错误。 C ++的设计理念之一是速度超过安全性。在C ++语言设计者看来,运行时检查会导致迭代器失效而不是未指定的行为太昂贵了。

  4. 当您迭代数据结构并修改结构本身而不仅仅是其中包含的对象时,您应该处于高度警戒状态。此时,您应该运行文档并检查操作是否非法。

答案 1 :(得分:6)

当迭代器类型(支持运算符++*的对象未正确表示正在迭代的对象的状态时,会发生迭代器失效 。例如:

int *my_array = new int[15];
int *my_iterator = &my_array[2];

delete[] my_array;

std::for_each(my_iterator, my_iterator + 5, ...); // invalid

这会导致未定义的行为,因为它指向的内存已被操作系统回收。

然而,这只是一种情况,而且许多其他因素导致迭代器“无效”,您必须小心检查正在使用的对象的文档。

答案 2 :(得分:4)

当使用迭代器处理的容器在此过程中更改其形状时,会发生此问题。 (我们将假设一个单线程应用程序;对可变容器的并发访问是一个整体'其他蠕虫,我们将不会在此页面上进入)。通过“改变形状”,意味着以下类型的突变之一:

  • 插入容器(在任何位置)
  • 删除 容器中的元素
  • 任何更改密钥的操作(在 AssociativeContainer)
  • 任何改变顺序的操作 已排序容器中的元素。
  • 任何更复杂的操作 由一个或多个上述组成(例如拆分容器) 分为两个)。

(来自:http://c2.com/cgi/wiki?IteratorInvalidationProblem

这个概念实际上相当简单,但副作用可能非常烦人。我想补充一点,这个问题不仅会影响C / C ++,还会影响其他低级或中级语言。 (在某些情况下,即使它们不允许直接堆分配)