为什么更喜欢std::vector而不是std::d eque

Why prefer std::vector over std::deque?

本文关键字:std eque vector 更喜欢 为什么      更新时间:2023-10-16

它们都具有O(1(的访问复杂度和O(n(的随机插入/删除复杂度。但是矢量在扩展时由于重新分配和复制而成本更高,而 deque 没有这个问题。

看起来 deque 有更好的性能,但为什么大多数人使用矢量而不是 deque?

why most people use vector instead of deque?

因为这是他们被教导的。

vectordeque的目的略有不同。 它们都可以用作对象的简单容器,如果这就是您所需要的。 当学习编程C++时,这就是大多数人所需要的——一个桶,可以把东西放进去,把东西拿出来,然后走过去。

当StackOverflow被问到诸如"默认情况下我应该使用哪个容器"之类的问题时,答案几乎总是vector。 这个问题通常是从学习C++编程的背景下提出的,当程序员问这样的问题时,他们还不知道他们不知道什么。 还有很多他们还不知道的。 因此,我们(StackOverflow(需要一个容器,它几乎可以满足所有更好或更坏的需求,几乎可以在任何上下文中使用,并且不需要程序员在找到接近正确答案的东西之前提出所有正确的问题。 此外,该标准特别建议使用vectorvector并不是对所有用途都是最好的,事实上,对于许多常见用途,dequevector更好——但对于一个学习程序员来说,我们应该从标准对新手C++程序员的建议中有所不同,所以 StackOverflow vector 登陆

在学习了语法的基础知识以及C++编程背后的策略之后,程序员分为两个分支:那些愿意学习更多并编写更好程序的人,以及那些不想学习的人。 那些不这样做的人将永远坚持vector。 我认为很多程序员都属于这个阵营。

那些试图超越这个阶段的程序员很少开始问其他问题——就像你在这里问过的问题。 他们知道还有很多他们还不知道的东西,他们想开始发现这些东西是什么。 他们会很快(或不太快(发现,在vectordeque之间进行选择时,他们以前没有想到要问的一些问题是:

  1. 我需要内存是连续的吗?
  2. 我需要避免大量重新分配吗?
  3. 插入后是否需要保留有效的迭代器?
  4. 我需要我的收藏与一些古老的类似 C 的功能兼容吗?

然后他们真的开始思考他们正在编写的代码,发现更多他们不知道的东西,节拍还在继续......

但是由于重新分配和复制,向量在扩展时成本更高

虽然vector有时确实必须随着数组的增长而重新分配其数组,但它将以指数方式增长,因此摊销的复杂性仍为 O(1(。通常,您可以通过明智地使用 reserve() 来避免重新分配。

似乎德克有更好的表现

性能有很多方面;push_back所花费的时间只是一个。在某些应用程序中,容器可能很少被修改,或者在启动时填充,然后永远不会被修改。在这种情况下,迭代和访问速度可能更重要。

vector是最简单的容器:一个连续的数组。这意味着迭代和随机访问可以通过简单的指针算法来实现,并且访问元素的速度可以与取消引用指针一样快。

deque还有进一步的要求:它不能移动元素。这意味着典型的实现需要额外的间接寻址级别 - 它通常实现为类似于指向数组的指针数组。这意味着元素访问需要取消引用两个指针,这将比一个指针慢。

当然,速度通常不是一个关键问题,您可以根据容器的行为属性而不是性能来选择容器。如果您需要元素是连续的,则可以选择vector,也许是为了使用基于指针和数组的 API。如果要保证元素不会移动,可以选择dequelist,以便可以存储指向它们的指针。

从C++标准第 23.1.1 节:

vector is the type of sequence that should be used by default... deque is 
the data structure of choice when most insertions and deletions take place
at the beginning or at the end of the sequence.

然而,有一些相反方向的论点。

从理论上讲,vector至少与deque一样有效,因为它提供了其功能的子集。如果你的任务只需要vector的接口提供什么,首选vector——它不能比deque差。

对于 cplusplus :

因此,它们提供与向量类似的功能,但具有 在元素的开头也能有效地插入和删除元素 序列,而不仅仅是在它的结尾。但是,与向量不同,deques 是 不保证将其所有元素存储在连续存储中 位置,因此不允许通过偏移指向的指针直接访问 元素。

就个人而言,我更喜欢使用deque(我总是最终宠坏自己,出于某种原因不得不使用push_front(,但vector确实有其用途/差异,主要的是:

vector具有连续的内存,而deque则通过页面/块进行分配。请注意,页面/块非常有用:容器正面的恒定时间插入/擦除。通常,分解成一系列较小块的大内存块比单个内存块更有效。

你也可以争辩说,因为deque"缺少"尺寸预订方法(capacity/reserve(,你不必担心。

我强烈建议你阅读萨特斯关于这个话题的GotW。