deque迭代器失效的困惑?

在实现LRU算法的时候lru_list 开始用的是deque 但是因为害怕其在插入删除上的迭代器失效情况的诡异情况。遂用list代替之。

在数据量比较大的时候性能不是很好。性能优化分析的时候决定用deque替换回来。于是对deque迭代器失效的情况好好研究了一下:

c++ primer如此写道:

1.在deque容器首部或者尾部插入元素不会使得任何迭代器失效。

2.在其首部或尾部删除元素则只会使指向被删除元素的迭代器失效。

3.在deque容器的任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器失效。

stackoverflow上对此的讨论:Confusion
on iterators invalidation in deque

I‘m bit confused regarding iterator invalidation in deque. (In the context of this question)

Following is the excerpts from -- The C++ Standard Library: A Tutorial and Reference, By Nicolai M. Josuttis

Any insertion or deletion of elements other than at the beginning or end invalidates all pointers, references, and iterators that refer to elements of the deque.

Following is the excerpts from SGI site:

The semantics of iterator invalidation for deque is as follows. Insert (including push_front and push_back)
invalidates all iterators that refer to a deque. Erase in the middle of a deque invalidates all iterators that refer to the deque. Erase at the beginning or end of a deque (including pop_front and pop_back)
invalidates an iterator only if it points to the erased element.

IMHO, deque is collection of blocks with first block growing in one direction and the last block in opposite direction.

  -   -  -
  -   -  -
  |   -  -  ^
  |   -  -  |
  V   -  -  |
      -  -  -
      -  -  -

push_back,
push_front
 should not have any impact on deque iterators ( I agree with Josuttis).

What is the correct explanation? what the standard say on this?

完美的答案:

IMHO, deque is collection of blocks with first block growing in one direction and the last block in opposite direction.

Your opinion is your prerogative, but it‘s wrong. :)

deque is
such a container semantically, but in terms of implementation it‘s designed to be implemented by one or more blocks of memory. C++‘s
iterator invalidation rules
 come from implementation, so this is why. Arguably this is a small abstraction leak but, well, whatever.

The SGI STL documentation is not the proper documentation to read, because the
SGI STL is not the C++ Standard Library
. Unfortunately, Josuttis is one of those people who calls it "the STL", and this has led to your confusion.


Following is the excerpts from -- The C++ Standard Library: A Tutorial and Reference, By Nicolai M. Josuttis

Any insertion or deletion of elements other than at the beginning or end invalidates all pointers, references, and iterators that refer to elements
of the deque.

Put simply, this passage from Josuttis is misleading in implying that the insertion or deletion of elements thatare at
the beginning or end do not invalidate pointers, references or iterators … though it‘s worth noting that he never comes out and asserts this outright.



Here are the real, proper, official rules for std::deque:

C++03

  • Insertion: all iterators and references are invalidated, unless the inserted member is at an end (front or back) of the deque (in which case all
    iterators are invalidated, but references to elements are unaffected) [23.2.1.3/1]
  • Erasure: all iterators and references are invalidated, unless the erased members are at an end (front or back) of the deque (in which case only iterators
    and references to the erased members are invalidated) [23.2.1.3/4]
  • Resizing: as per insert/erase [23.2.1.2/1]

C++11

  • Insertion: all iterators and references are invalidated, unless the inserted member is at an end (front or back) of the deque (in which case all
    iterators are invalidated, but references to elements are unaffected) [23.3.3.4/1]
  • Erasure: erasing the last element invalidates only iterators and references to the erased elements and the past-the-end iterator; erasing the first
    element invalidates only iterators and references to the erased elements; erasing any other elements invalidates all iterators and references (including the past-the-end iterator) [23.3.3.4/4]
  • Resizing: as per insert/erase [23.3.3.4/1]

Further reading

时间: 2024-10-12 13:55:32

deque迭代器失效的困惑?的相关文章

C++中防止STL中迭代器失效——map/set等关联容器——vector/list/deque等序列容器—如何防止迭代器失效—即erase()的使用

序列性容器::(vector和list和deque) erase迭代器不仅使所有指向被删元素的迭代器失效,而且使被 删元素之后的所有迭代器失效,所以不能使用erase(iter++)的方 式,但是erase的返回值为下一个有效的迭代器,所以   正确方法为:: for( iter = c.begin(); iter != c.end(); ) iter = c.erase(iter); 关联性容器::(map和set比较常用) erase迭代器只是被删元素的迭代器失效,但是返回值为void, 所

STL源码分析--迭代器总结、迭代器失效总结

Vector 1.内部数据结构:连续存储,例如数组. 2.随机访问每个元素,所需要的时间为常量. 3.在末尾增加或删除元素所需时间与元素数目无关,在中间或开头增加或删除元素所需时间随元素数目呈线性变化. 4.可动态增加或减少元素,内存管理自动完成,但程序员可以使用reserve()成员函数来管理内存. 5.迭代器失效 插入:vector的迭代器在内存重新分配时将失效(它所指向的元素在该操作的前后不再相同).当把超过capacity()-size()个元素插入vector中时,内存会重新分配,所有

STL迭代器失效总结

转自: http://blog.csdn.net/hackbuteer1/article/details/7734382             http://m.blog.csdn.net/blog/xhu_eternalcc/38355619 迭代器(iterator)是一个可以对其执行类似指针的操作(如:解除引用(operator*())和递增(operator++()))的对象,我们可以将它理 解成为一个指针.但它又不是我们所谓普通的指针,我们可以称之为广义指针,你可以通过sizeof(

C++: STL迭代器及迭代器失效问题

转载至:http://blog.csdn.net/wangshihui512/article/details/9791517 迭代器失效: 典型的迭代器失效. 首先对于vector而言,添加和删除操作可能使容器的部分或者全部迭代器失效.那为什么迭代器会失效呢?vector元素在内存中是顺序存储,试想:如果当前容器中已经存在了10个元素,现在又要添加一个元素到容器中,但是内存中紧跟在这10个元素后面没有一个空闲空间,而vector的元素必须顺序存储一边索引访问,所以我们不能在内存中随便找个地方存储

vector和map的迭代器失效问题

1.vector #include <iostream> #include <string> #include <vector> using namespace std; void vectorTest() { vector<int> container; for (int i = 0; i < 10; i++) { container.push_back(i); } vector<int>::iterator iter; for (ite

stl迭代器失效

迭代器(iterator)是一个可以对其执行类似指针的操作(如:解除引用(operator*())和递增(operator++()))的对象,我们可以将它理解成为一个指针.但它又不是我们所谓普通的指针,我们可以称之为广义指针,你可以通过sizeof(vector::iterator)来查看,所占内存并不是4个字节.     首先对于vector而言,添加和删除操作可能使容器的部分或者全部迭代器失效.那为什么迭代器会失效呢?vector元素在内存中是顺序存储,试想:如果当前容器中已经存在了10个元

容器操作使迭代器失效

一.向容器添加元素时 ①vector & string if 储存空间重新分配 迭代器.引用&指针都失效 if 没有重新分配  插入位置之前都有效 ②deque 插入到除首尾外都会失效 if 首尾添加,迭代器失效,其他不失效 ③list & forward_list 都有效 二.从容器中删除元素 ①list & forward_list 指向容器其他的任有效 ②deque 删除首&非尾的其他,任有效 删除尾元素,都失效 ③vector & string 被删

C++迭代器失效的问题 汇总

首先对于vector而言,添加和删除操作可能使容器的部分或者全部迭代器失效.那为什么迭代器会失效呢?vector元素在内存中是顺序存储,试想:如果当前容器中已经存在了10个元素,现在又要添加一个元素到容器中,但是内存中紧跟在这10个元素后面没有一个空闲空间,而vector的元素必须顺序存储一边索引访问,所以我们不能在内存中随便找个地方存储这个元素.于是vector必须重新分配存储空间,用来存放原来的元素以及新添加的元素:存放在旧存储空间的元素被复制到新的存储空间里,接着插入新的元素,最后撤销旧的

迭代器失效~转载

迭代器失效: 典型的迭代器失效. 首先对于vector而言,添加和删除操作可能使容器的部分或者全部迭代器失效.那为什么迭代器会失效呢?vector元素在内存中是顺序存储,试想:如果当前容器中已经存在了10个元素,现在又要添加一个元素到容器中,但是内存中紧跟在这10个元素后面没有一个空闲空间,而vector的元素必须顺序存储一边索引访问,所以我们不能在内存中随便找个地方存储这个元素.于是vector必须重新分配存储空间,用来存放原来的元素以及新添加的元素:存放在旧存储空间的元素被复制到新的存储空间