注:想要理解本篇博客,需要读者有基本的 vector 的知识,请看博主的另一篇文章: https://blog.csdn.net/qq_41291253/article/details/89840185
一、deque 简介
(1)deque:双端队列
template <class T,class Alloc = allocator < T >> class deque;
//T - 元素的类型。别名为成员类型deque :: value_type。
//alloc - 用于定义存储分配模型的分配器对象的类型。默认情况下,使用allocator类模板,该模板定义最简单的内存分配模型,并且与值无关。
双端队列是double-ended queue不规则的缩写。双端队列是具有动态大小的序列容器,可以在两端(前端或后端)扩展或收缩。
特定库可以以不同方式实现deques,通常是动态数组的某种形式。但无论如何,它们允许通过随机访问迭代器直接访问各个元素,并根据需要通过扩展和收缩容器来自动处理存储。
因此,deque提供类似于vector的功能,但在序列的开头也有可以插入和删除元素,而不仅仅是在其结尾。但是,与vector不同,deques不能保证将其所有元素存储在连续的存储位置中:deque通过将指针偏移(如p++,p 为指针类型)到另一个元素来访问 该元素会导致未定义的行为。
vector和deques 两者提供了一个非常相似的接口,可以用于类似的目的,但内部是以完全不同的方式工作:虽然vector使用需要偶尔重新分配用于增长的单个数组,但是双端队列的元素可以分散在不同的块中存储,容器在内部保存必要的信息,以便在恒定时间内通过统一的顺序接口(通过迭代器)直接访问其任何元素。因此,deques在内部比vector稍微复杂一些,但是这允许deque在非常长的序列中更有效地扩展,但是在这种情况下,重新分配内存变得更加耗费时间。例如,对于 6M 数据,vector 需要连续的 6M 内存;deque 可能需要 6 个 1M 内存。
对于在开始或结束之外的位置频繁插入或删除元素的操作,deque的性能更差,而且迭代器和引用的一致性比list和forward list差。
(2)容器属性
序列:序列容器中的元素按严格的线性顺序排序。各个元素按其顺序访问它们的位置。
动态数组:通常实现为动态数组,它允许直接访问序列中的任何元素,并在序列的开头或结尾提供相对快速的元素添加/删除。
分配器感知:容器使用allocator对象来动态处理其存储需求。
(3)deque和 vector 区别
- deque 两端都能快速插入和删除元素,复杂度不变;而 vector 只能在尾端快速插入元素,在首端插入元素需要移动所有数据,时间复杂度为n。
- 因内存区域不连续,所以++it,--it 操作可能会出错,而 vector 是连续存储,则不存在这一现象。
- 元素的存取和迭代器的动作相对 vector 慢。
- 因为deque使用不止一块内存,所以deque的max_size()可能更大。
- 双端队列的元素可以分散在不同的块中存储,容器在内部保存必要的信息,以便在恒定时间内通过统一的顺序接口(通过迭代器)直接访问其任何元素。因此,deques在内部比vector稍微复杂一些,但是这允许deque在非常长的序列中更有效地扩展,但是在这种情况下,重新分配内存变得更加耗费时间。
- 除了头尾两端,在任何地方安插或删除元素,都将导致指向deque元素的所有pointers、references、iterators失效。
- deque的内存区块不再被使用时,会自动被释放。deq