C++ 为什么我更喜欢使用vector而不是deque

C++ 为什么我更喜欢使用vector而不是deque,c++,stl,vector,deque,C++,Stl,Vector,Deque,自 它们都是连续的内存容器 就功能而言,deque几乎拥有vector所拥有的一切,但更多,因为在前端插入更有效 为什么有人更喜欢std::vector而不是std::deque?std::deque没有保证的连续内存,而且索引访问通常会稍微慢一些。deque通常被实现为一个“向量列表”。deque是一个序列容器,它允许对其元素进行随机访问,但不保证具有连续存储。deque中的元素在内存中不连续矢量元素保证为。因此,如果您需要与需要连续数组的普通C库交互,或者如果您非常关心空间局部性,那么您可能

  • 它们都是连续的内存容器
  • 就功能而言,deque几乎拥有vector所拥有的一切,但更多,因为在前端插入更有效

  • 为什么有人更喜欢
    std::vector
    而不是
    std::deque

    std::deque
    没有保证的连续内存,而且索引访问通常会稍微慢一些。deque通常被实现为一个“向量列表”。

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

    deque中的元素在内存中不连续<代码>矢量元素保证为。因此,如果您需要与需要连续数组的普通C库交互,或者如果您非常关心空间局部性,那么您可能更喜欢
    vector
    。此外,由于存在一些额外的簿记,其他运营可能(稍微)比其等价的
    vector
    运营更昂贵。另一方面,使用
    vector
    的许多/大型实例可能会导致不必要的堆碎片(减慢对
    new
    的调用)

    此外,正如所指出的,这里有更多好的讨论:

    根据“与向量不同,不能保证DEQUE的所有元素都位于连续的存储位置,从而消除了通过指针算法进行安全访问的可能性。”

    DEQUE有点复杂,部分原因是它们不一定有连续的内存布局。如果您需要该功能,则不应使用deque


    (之前,我的回答提出了缺乏标准化的问题(来自与上面相同的来源,“deque可能由特定的库以不同的方式实现”),但这实际上适用于几乎任何标准库数据类型。)

    我已经多次实现了vector和deque。从实现的角度来看,deque要复杂得多。这种复杂性会导致更多的代码和更复杂的代码。因此,当您选择deque而不是vector时,通常会看到代码大小受到影响。如果您的代码只使用向量擅长的东西(即推回),您也可能会遇到一个小的速度冲击


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

    我认为最好对每个案例进行性能测试。并根据这些测试做出决定


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

    要了解区别,人们应该知道
    deque
    通常是如何实现的。内存以相同大小的块分配,并将它们链接在一起(作为数组或向量)

    因此,要找到第n个元素,您需要找到相应的块,然后访问其中的元素。这是常数时间,因为它总是正好是2次查找,但这仍然比向量大

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

    其中,
    deque
    最大的优点是:

  • 从两端增加或缩小集合时
  • 当您处理非常大的集合大小时
  • 在处理bools时,您确实想要bools而不是位集
  • 第二个是鲜为人知的,但对于非常大的集合大小:

  • 重新分配的成本很高
  • 必须查找连续内存块的开销是有限的,因此可以更快地耗尽内存
  • 当我过去处理大型集合时,从连续模型转移到块模型,在32位系统内存耗尽之前,我们能够存储大约5倍大的集合。这部分是因为,在重新分配时,它实际上需要在复制元素之前存储旧块和新块

    话虽如此,在使用“乐观”内存分配的系统上,您可能会遇到使用
    std::deque
    的麻烦。虽然它试图请求较大的缓冲区大小以重新分配
    向量
    ,但在某个时候可能会被
    错误分配
    拒绝,分配器的乐观性质可能总是允许对
    deque
    请求的较小缓冲区的请求,这可能会导致操作系统终止进程以尝试获取一些内存。无论它选择哪一个,都可能不太令人愉快


    在这种情况下,解决方法是设置系统级标志以覆盖乐观分配(并非总是可行的),或稍微手动管理内存,例如使用自己的分配器检查内存使用情况或类似情况。显然不理想。(这可能会回答您关于更喜欢向量的问题…

    根据

    当然,您应该在应用程序/环境中进行测试,但总而言之:

    • 推回基本上对所有人都是一样的
    • deque中的insert、erase比list快得多,比vector快得多

    一方面,vector通常比deque快得多。如果您实际上不需要deque的所有功能,请使用向量

    另一方面,有时您确实需要向量没有提供的特征,在这种情况下,您必须使用deque。例如,我要求任何人尝试重写,而不使用deque,也不大幅修改算法。