为什么我更喜欢使用vector来检测

以来

  1. 他们都是连续的记忆容器;
  2. 特征明智,deque几乎所有的vector,但更多,因为它是更有效的插入在前面。

为什么有人更喜欢std::vectorstd::deque

记忆中的元素不是连续的; vector元素保证是。 所以如果你需要和一个需要连续数组的C库相互作用,或者你关心空间局部性,那么你可能更喜欢vector 。 此外,由于有一些额外的簿记,其他操作可能(稍微)比等同的vector操作更昂贵。 另一方面,使用很多/大的vector实例可能会导致不必要的堆碎片(将调用放慢)。

另外,正如在StackOverflow的其他地方所指出的,这里有更多的讨论: http : //www.gotw.ca/gotw/054.htm 。

要知道差异,应该知道一般如何执行deque 。 内存以相同大小的块分配,并且链接在一起(作为一个数组或可能是一个向量)。

因此,要find第n个元素,您可以find适当的块,然后访问其中的元素。 这是不变的时间,因为它总是正好两个查找,但是这仍然比vector更多。

vector也适用于需要连续缓冲区的API,因为它们要么是C API,要么是能够获取指针和长度的更多function。 (因此,你可以有一个向下或一个常规数组,并从您的内存块调用API)。

deque有其最大的优势是:

  1. 从任何一端扩大或缩小收集
  2. 当你正在处理非常大的collections大小。
  3. 当处理bools,你真的想要bools而不是一个bitset。

其中的第二个是鲜为人知的,但对于非常大的收集尺寸:

  1. 重新分配的成本很大
  2. 必须查找连续内存块的开销是有限制的,因此可以更快地耗尽内存。

当我在过去处理大型集合,并从连续模型转移到块模型时,在32位系统内存耗尽之前,我们能够存储大约5倍的集合。 这部分是因为在重新分配时,实际上需要在复制元素之前存储旧块和新块。

说完这一切,你可以在使用“乐观”内存分配的系统上遇到std::deque问题。 虽然尝试请求较大的缓冲区大小以重新分配vector可能会在某个点被bad_alloc拒绝,但分配器的乐观性总是可能总是为请求由deque请求的较小缓冲区提供请求,可能会导致操作系统杀死一个进程来尝试获取一些内存。 无论select哪一个可能都不太愉快。

在这种情况下的解决方法是设置系统级标志来覆盖乐观分配(不总是可行的)或者更手动地pipe理内存,例如使用自己的分配器来检查内存使用情况或类似情况。 显然不理想。 (这可能会回答你的问题,喜欢vector…)

我已经实现了vector和deque多次。 从实现的angular度来看,deque是非常复杂的。 这种复杂性转化为更多的代码和更复杂的代码。 所以当你select向量上的双向转换时,你通常会看到一个代码大小的问题。 如果你的代码只使用向量擅长的东西(例如push_back),你也可能遇到小的速度。

如果你需要一个双端队列,deque是明确的赢家。 但是如果你在大部分插入和删除后面,vector将是明确的赢家。 当你不确定的时候,用一个typedef声明你的容器(这样很容易来回切换),然后测量。

std::deque没有保证连续的内存 – 而且对于索引访问来说通常会稍微慢一些。 deque通常被实现为“vector列表”。

根据http://www.cplusplus.com/reference/stl/deque/ ,“不像载体,deques不能保证所有的元素在连续的存储位置,从而消除通过指针算术安全访问的可能性。

Deques有点复杂,部分原因是它们不一定有连续的内存布局。 如果你需要这个function,你不应该使用一个双端队列。

(之前,我的答案带来了缺乏标准化的问题(从上面的同一来源,“deques可能以不同的方式由特定的库实现”),但是实际上它适用于任何标准库数据types。

deque是一个序列容器,允许随机访问它的元素,但不保证有连续的存储。

我认为对每个案例进行性能testing是个好主意。 并依靠这个testing做出决定。

在大多数情况下,我更喜欢std::deque不是std::vector

根据这些testing结果(源代码),你不会select向量。

当然,你应该在你的应用程序/环境中进行testing,但总的来说:

  • push_back对于所有人来说基本上是一样的
  • 插入,在德克擦除比列表快得多,边缘比vector快

一些更多的沉思,和一个笔记考虑circular_buffer。

一方面,vector往往比deque更快。 如果你实际上不需要 deque的所有function,使用一个向量。

另一方面,有时候你确实需要vector不能给你的function,在这种情况下你必须使用一个双引擎。 例如,我挑战任何人尝试重写这段代码 ,而不使用双端队列,也不会极大地改变algorithm。