什么是迭代器失效?

Mar*_*las 34 c++ iterator

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

什么是迭代器失效?

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

dje*_*lin 40

  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
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 因为那个错误就在那里?没有编译器错误,没有警告,你输了.你只需要训练得足以观察它们并防止它们.如果你不知道你在做什么,那就是非常阴险的错误.C++的设计理念之一是速度超过安全性.在C++语言设计者看来,运行时检查会导致迭代器失效而不是未指定的行为,因此过于昂贵.

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

  • 这就是我喜欢Visual Studio具有调试版本的原因.默认情况下,标准C++容器将检查它们是否在调试版本中有效,从而帮助查找这些潜在的错误. (10认同)
  • @MarkCanlas:这就是C++的工作原理.大多数只能在运行时捕获的错误不需要自动检查; 否则,在许多情况下运行时成本是不可接受的.因此,"安全"实现(如Mooing Duck所述)将检查此错误; "快速"实施不会,而且速度会快得多. (7认同)
  • @ RichardJ.RossIII:取决于?显然不是.但是当我搞砸的时候,有一个额外的保护层是很好的. (6认同)

Ric*_*III 7

迭代器失效是当一个迭代器类型(对象支持运营商会发生什么++,以及*)不正确地表示其重复所述对象的状态.例如:

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

delete[] my_array;

std::for_each(my_iterator, my_iterator + 5, ...); // invalid
Run Code Online (Sandbox Code Playgroud)

这导致未定义的行为,因为它指向的内存已被OS回收.

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


Dav*_*nco 5

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

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

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

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