列表超过向量的好处?

时间:2009-05-25 15:08:07

标签: c++ list stl vector

我需要的只是一个动态增长的数组。我不需要随机访问,我总是插入到最后并从头到尾阅读它。

slist似乎是第一选择,因为它提供了我所需要的足够的东西。但是,我不知道通过使用slist而不是vector来获得什么好处。此外,我读到的关于STL的一些材料说,“向量通常是访问元素和从序列末尾添加或删除元素的最有效时间”。因此,我的问题是:对于我的需求,slist真的比矢量更好吗?提前谢谢。

6 个答案:

答案 0 :(得分:13)

首先,slist是非标准的。

根据您的选择,链接列表将比矢量慢,依赖它。造成这种情况的原因有两个:

  1. 首先,缓存局部性;向量将它们的元素线性地存储在RAM中,这有利于缓存和预取。
  2. 其次,附加到链接列表涉及动态分配,这会增加很大的开销。相比之下,矢量大多数情况下需要分配内存。
  3. 然而,std::deque可能会更快。 In-depth performance analysis已经表明,尽管有相反的偏见,std::deque在性能上几乎总是优于std::vector(如果不需要随机访问),因为其改进(分块)内存分配策略。

答案 1 :(得分:3)

是的,如果你总是从头开始阅读,slist(一个链表)听起来就像是要走的路。可能的例外是,如果您将同时在末尾插入大量元素。然后,如果适当使用保留,向量可能会更好。

当然,配置文件以确保您的应用程序更好。

答案 2 :(得分:2)

Matt Austern(“通用编程和STL”的作者和普通的C ++大师)是单链表的强力倡导者,可以包含在即将推出的C ++标准中。请参阅他在http://www.accu-usa.org/Slides/SinglyLinkedLists.ppt的演讲以及他在http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2543.htm的长篇文章了解更多细节,包括讨论所涉及的权衡,可能会指导您选择这种数据结构。 (请注意,当前提议的名称为forward_list,但slist是传统上在SGI的STL和其他常用库中命名的名称。

答案 3 :(得分:2)

我将第二(或可能是第三......)std::vectorstd::deque将履行职责的意见。我要添加的唯一内容是指导std::vector<T>std::list<T>之间决策的其他一些因素。这些与T的特征以及您计划使用的算法有很大关系。

第一个是内存开销。 Std::list是一个基于节点的容器,因此如果T是基本类型或相对较小的用户定义类型,那么基于节点的链接的内存开销可能是不可忽略的 - 考虑std::list<int> 1}}可能至少为每个元素使用3 * sizeof(int)存储,而std::vector仅使用sizeof(int)存储,并且头部开销较小。 Std::dequestd::vector类似,但开销很小,与N呈线性关系。

下一个问题是复制构建的成本。如果T(T const&)非常昂贵,那么请避开std::vector<T>,因为随着向量的大小增加,会导致出现大量副本。这是std::deque<T>明显赢家的地方,std::list<T>也是竞争者。

通常指导容器类型决策的最后一个问题是您的算法是否可以使用std::vectorstd::deque的迭代器失效约束。如果你将大量操作容器元素(例如,排序,插入中间或改组),那么你可能希望倾向于std::list,因为操纵顺序只需要重置几个连接指针。

答案 4 :(得分:1)

我猜你的意思是std :: list by“slist”。当你需要快速,随机访问一系列元素,保证连续内存和快速顺序读取(IOW,从开始到结束)时,向量很好。当您需要在序列的开头或结尾快速(恒定地)插入或删除项目时,列表很好,但不关心随机访问或顺序读取的性能。

区别的原因是2的实施方式。向量在内部实现为项目数组,在添加项目时达到其大小/容量时需要重新分配。列表被实现为双向链表,这可能导致顺序读取的高速缓存未命中。列表的随机访问还需要从列表中的第一个(或最后一个)项目进行扫描,直到找到您要求的项目为止。

答案 5 :(得分:0)

对我来说, std :: deque 听起来不错。它具有向量的内存优势,例如每个“slab”的连续内存分配(适用于CPU缓存),没有像std :: list那样的每个元素的开销,并且它不需要将整个集重新分配为std :: vector确实。详细了解std::deque here