STL deque是作为循环链表实现的
本文关键字:循环链表 实现 deque STL | 更新日期: 2023-09-27 17:48:59
我无法找到deque在c++ STL中如何实现的内部信息。
我以前在某个地方读到过,在c#中它是作为循环列表实现的。c++ STL也是这样吗?另外,你能解释一下为什么会这样吗?
编辑:这里的c++ STL,我指的是Visual studio c++ 2010附带的STL库,以及gcc附带的STL库No。它的实现方式有一些变化,但循环链表肯定不符合的条件。
在大多数实现中(包括vc++和可能的gcc),它基本上是一个指向数据块的指针数组。当您添加数据时,它通常只是将其添加到现有的数据块中。当现有块填满时,它会分配一个新的块,将其添加到您正在插入的数组的末尾,然后将数据添加到其中。
c++标准要求deque具有恒定的随机查找时间。循环链表不符合要求。
STL是规范,而不是实现。规范没有要求如何实现行为(只要它遵守定义的接口)。
deque
的实现必须提供
- 对其元素的常数时间随机访问
- 恒时末端插入和移除
- 起始恒时插入和移除
(1)排除任何类型的链表,包括循环链表
(2),(3)排除存储元素的简单内存块。
注意:现行标准('03)实际上说的是常数时间而不是平摊常数时间对于(2)&(3)(见23.2.1/1
),但我认为这是一个疏忽。我不知道如何在常数时间中完成这三个。如果(1)只有常数时间,(2)和(3)只有平摊常数时间,那么就很容易了。
MSVC deque
使用指向元素页的指针的环缓冲区。可以把环形缓冲区看作一个带有偏移量+环绕的数组(vector
)。一个页面包含少量元素(IIRC不超过8个),这取决于sizeof(element)
。如果需要更多的空间,环缓冲区就像std::vector
一样增长(这就是您需要平摊常数时间而不是常数时间的地方)。
我认为其他实现(GCC,…)将非常相似。
BTW:在标准中还有一个子句,使得不可能只使用一个大的元素环缓冲区,而不使用"指针索引"。23.2.1.3/1
表示在开头或结尾插入不会使对deque
中元素的引用无效。显然,如果保存元素本身的结构在超出保留空间时必须重新分配,则这是不可能的。普通的环形缓冲区需要这样做,因此不能使用。