为什么std::vector比std::deque更受欢迎

Why is std::vector so much more popular than std::deque?

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

可能的重复:
为什么我更喜欢使用矢量来消除

我很好奇为什么std::vectorstd::deque更受欢迎。Deque在查找方面几乎同样高效,在插入方面更高效(没有vector::reserve),并允许在前面插入/删除。

赫伯·萨特曾建议,若你们想使用矢量,那个就更喜欢deque(我是转述)。然而,在最近一次关于编写现代C++的演讲中,他再次强烈建议将std::vector作为默认容器。根据我之前链接的GOTW,即使是标准也有类似的措辞。

造成这种差距的原因是什么?只是vector更简单、更广为人知,还是有技术原因?还是vector只是一个更酷的名字?

我不能为别人说话,但我可以为自己说话。

当我第一次读到std::deque时,我觉得它很酷,有一段时间,我不仅把它当作默认容器,而且几乎把它当作我使用的仅容器。

然后有人问为什么,我详细阐述了它的优点,为什么它是几乎所有东西的最佳容器,以及它是如何比std::vector更通用的。

幸运的是,那个质疑我决定的人足够有说服力,我做了一些测试。测试表明,几乎在所有情况下,std::deque都比std::vector慢——通常是一个重要因素(例如,大约2)。事实上,在我使用std::deque编写的代码中,仅用std::vector替换std::deque就可以在除少数情况外的所有情况下加速。

从那以后,我在一些情况下使用了std::deque,但绝对不再将其视为默认值。简单的事实是,在通常的实现中,对于的大多数目的,它明显慢于std::vector

然而,我应该补充一点,我有理由确信,如果实现正确,它在几乎所有情况下都可以几乎等同于std::vector。大多数人使用的表示从渐进的角度来看无疑是很好的,但在现实世界中(出于许多目的)效果并不那么好。

std::vector非常容易理解、简单,并且与C兼容(无论是在内存布局方面,还是在使用指针作为迭代器方面)。

对于某些操作,它也比std::deque更有效。通过索引访问元素就是一个例子。

对于给定的任务,使用最简单的容器来完成任务是有意义的。在许多情况下,最简单的容器是std::vector

人们使用std::vector而不是std::deque的原因很简单。它们与许多C库接口,并且它们有一些带有参数的函数,这些函数需要指向连续存储的指针,而std::deque不能保证这一点。

另一个原因是,当您根据std::deque构建代码,并且您的需求发生了变化,因此您必须支持连续访问时,您将需要进行一些重构

我不得不提到,有些库的作者声称已经创建了更高效的矢量实现,以便在容量增加时克服效率低下的问题。

std::deque的结构有点复杂,这使得天真迭代比std::vector要贵得多。插入到std::vector及其重新定位往往不是什么大问题,尤其是当使用reserve()并仅附加到末尾时。此外,std::vector有更容易理解的无效规则,尽管实际上std::deque的一个优点是,当只在两端插入/删除对象时,对象保持不变(注意,std::deque迭代器在每次插入时都会失效,与插入发生的位置无关)。std:vector的另一个优点是保证值在内存中是连续的,从而减少内存分配。

我想,我建议使用std::deque算法,这些算法一直被优化为使用分段序列(我不知道有任何标准C++库可以进行这种优化),并且用户一直在使用算法访问序列(据我所知,只有一小部分用户考虑使用算法的选项)。否则,我会怀疑std::deque在性能方面是更好的选择,只有当你利用它的特定属性时(例如,对象保持不变,并且你可以在最后插入/删除)。不过,值得对这两种选择进行分析。

除了std::vector是最常见的容器类外,它还比std::deque有几个优点,即:

  • std::vector的情况不同,典型的std::deque需要额外的间接访问来访问elment
  • std::deque的情况下,迭代程序必须是智能指针,而不是像在std::vector的情况下那样的指针
  • std::vector的元素保证是连续的,因此它与以数组为参数的c样式函数兼容
  • std::deque不提供控制容量和重新分配时刻的支持

特别是最后一点值得注意。