38

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

什么是迭代器失效?

为什么会出现?为什么很难对付?

4

3 回答 3

42
  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++ 语言设计者看来,将导致迭代器失效而不是未指定行为的运行时检查过于昂贵。

当您迭代数据结构并修改结构本身时,您应该保持高度警惕,而不仅仅是其中包含的对象。那时您可能应该跑到文档并检查该操作是否非法。

于 2013-06-03T19:36:03.977 回答
10

迭代器失效是当迭代器类型(支持运算符++和的对象*不能正确表示它正在迭代的对象的状态时发生的情况。例如:

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

delete[] my_array;

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

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

然而,这只是一种情况,还有许多其他事情会导致迭代器“无效”,您必须仔细检查您正在使用的对象的文档。

于 2013-06-03T19:36:19.233 回答
4

当使用迭代器处理的容器在处理过程中其形状发生变化时,就会出现此问题。(我们将假设一个单线程应用程序;对可变容器的并发访问是一个完整的“另一个蠕虫罐头,我们不会在此页面上讨论)。“改变其形状”是指以下类型的突变之一:

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

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

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

于 2013-06-03T19:37:21.467 回答