迭代器失效规则
这个问题在这里已经有了答案:
这些规则是特定于容器的。 实际上,这些是决定使用哪个容器的重要标准。
例如,当插入一个对象时(取决于对象被插入的位置以及是否发生重新分配),对std::vector
迭代器可能会失效,并且在迭代器之前删除对象时它们将失效。 一个std::list
没有这个问题。 插入和删除对象(迭代器指向的对象除外)不会使迭代器失效。
SGI提供了很好的文档。
无效规则来自用于实现这些容器的非常基本的数据结构和算法 。 如果你不打算学习基础知识,那么你需要记住迭代器文档。
C ++标准以一种可以用简单的C指针实现的方式定义了iterator
的行为。 它不需要库实际使用指针; 它只是使得这样做成为可能。
基本上,如果一个操作导致底层存储元素的迭代被无效(在所使用的堆阵列vector
,在所使用的链表节点list
中所使用的树节点,或map
或set
)到被解除分配,或shifed进入不同的存储位置。
通常通过从动态内存(堆)分配数组来实现vector
。 为了减少重新分配的次数,该数组总是被分配一些松弛,即最初未使用的空间。 随着元素被添加到数组中,松弛空间被用完。 当所有松弛空间被占用并且需要插入新元素时,将分配具有更大尺寸的新阵列。 这将导致所有迭代器指向旧数组的失效。
同样,当一个元素从vector
删除时,这将导致所有后续元素被向前复制。 指向移位元素的迭代器仍将引用数组中的相同索引,但该索引现在包含不同的元素。 这也是失效的一个例子。
对于list
, map
和set
,树节点或列表节点保持有效,直到它所包含的元素被擦除。 请注意,指向无效节点的迭代器不能用于任何事情; 甚至不用于迭代器递增/递减。 这是因为在链表或树实现中,迭代器依赖于存储在节点本身中的子指针。
为了始终保证正确的操作,与使用简单的数据结构相比,这种标准的表达方式更加严格(这种方式反而给图书馆实施人员更多的使用更高级的数据结构的自由)。 例如,请参阅http://c2.com/cgi/wiki?IteratorInvalidationProblem和http://www.threadingbuildingblocks.org/codesamples.php。
链接地址: http://www.djcxy.com/p/73331.html