为了使得这些分段的连续空间看起来像是一个整体,deque的迭代器必须有这样的能力:它必须能够指出分段连续空间在哪里,判断自己所指的位置是否位于某一个缓冲区的边缘,如果位于边缘,则执行operator-- 或operator++时要能够自动跳到下一个缓冲区。因此,尽管deque的迭代器也是Ramdon Access Iterator 迭代器,但它的实现要比vector的复杂太多。SGI版本的STL deque实现思路可以看侯捷的《STL源码剖析》。
迭代器失效问题如果向一个空deque插入元素,或删除一个元素后使deque为空,则原来指向begin()与end()的迭代器失效。
如果从deque的头部/尾部插入/删除元素,则所有的迭代器均失效,但是指向存在元素的引用和指针不会失效。
除了首尾位置,从其他任何位置的插入/删除都会使所有的迭代器、指针、引用失效。
如果删除deque的头部/尾部的元素,只有原来指向被删除元素的迭代器失效。
容器适配器stack,也称为栈,是一种先进后出的数据结构。STL中的statck是一种容器适配器。所谓的容器适配器,是以某种容器作为底部容器,在底部容器之上修改接口,形成另一种风貌。stack默认以双端队列deque作为底部容器。stack没有提供迭代器,通过push/pop接口对栈顶元素进行操作。
queue,也称为队列,是一种先进先出的数据结构,它同样也是一种容器适配器。它的底部容器默认为deque。同样,queue也没有提供迭代器,通过push向队尾压入元素,pop从队首弹出元素。
priority-queue,优先队列,是一种拥有权值观念的队列,例如在以整数大小作为衡量的权值定义下,priority-queue总是弹出最大的数。priority-queue的底部数据结构默认是max-heap,大顶堆。
总结 容器底层数据结构元素访问方式插入或删除元素效率迭代器失效情况array 固定大小的数组 支持快速随机访问 不能添加或删除元素 通常不会发生迭代器失效,除非对象已经被销毁,则原来的迭代器全部失效
vector 可动态增长的数组 支持快速随机访问 尾部可高效插入/删除元素 若插入操作引起内存重新分配,则全部迭代器失效;否则插入点/删除点之后的迭代器失效;
list 双向链表 只支持元素的双向顺序访问 在list的任何位置可高效插入/删除元素 插入操作后指向容器的迭代器有效;删除操作指向其他位置的迭代器有效
deque 双端队列 支持快速随机访问 首尾可高效插入/删除元素 情况较多,见上面分析
forward_list 单向链表 只支持元素的单向顺序访问 在链表的任何位置可高效插入/删除元素 插入操作后指向容器的迭代器有效;删除操作指向其他位置的迭代器有效
string 只存储字符元素的动态数组 支持快速随机访问 尾部可高效插入/删除元素 若插入操作引起内存重新分配,则全部迭代器失效;否则插入点/删除点之后的迭代器失效;
stack 默认deque 先进后出,只能访问栈顶元素 ---- 没有迭代器
queue 默认deque 先进先出,只能访问队首元素 ---- 没有迭代器
priority-queue 默认max-heap 先进先出,只能访问队首元素 ---- 没有迭代器
注意:
“尾部可高效插入/删除元素”,意味着在除了尾部之外的其他位置插入/删除元素是较低效的。
“顺序访问”意味着要访问某一个元素,必须遍历其他元素。
迭代器失效意味着指针、引用在同样的情况下也会失效。