矢量与在STL列表矢量与在STL列表(vector vs. list in STL)

2019-05-09 01:27发布

我在STL有效注意到,

载体是默认情况下应使用序列的类型。

什么意思? 似乎忽视了效率vector可以做任何事情。

可能有人给我提供这样一个场景, vector不是一种可行的选择,但list必须使用?

Answer 1:

要插入大量的项目到任何地方,但一个序列的重复结束的情况。

检查出各种不同类型的容器的复杂度保证:

什么是标准集装箱的复杂度保证?



Answer 2:

向量:

  • 连续的内存。
  • 预分配的空间为未来的元素,超出了必要内容本身需要这样的额外空间。
  • 每个元素只需要为元素类型本身的空间(没有额外的指针)。
  • 整个向量可以重新分配内存,你添加元素的任何时间。
  • 在端部的插入是恒定的,摊销时间,但插入在别处是一个昂贵的O(N)。
  • 在该载体的末端擦除是恒定时间,但其余它的O(N)。
  • 您可以随机访问它的元素。
  • 如果您添加或删除元素或者从矢量迭代器失效。
  • 您可以在下面的数组中很容易得到,如果你需要的元素的数组。

列表:

  • 非连续的存储器。
  • 没有预分配的内存。 对于列表本身的内存开销是恒定的。
  • 每个元素都需要持有的元素,包括指针到列表中的下一个和以前的元素节点额外的空间。
  • 从来没有为整个列表重新分配内存,仅仅因为你添加的元素。
  • 插入和删除很便宜无论身在何处列表中,他们发生。
  • 这是廉价的名单与拼接相结合。
  • 你不能随意访问元素,因此让在列表中的特定元素可以是昂贵的。
  • 甚至当您添加或删除列表中的元素的迭代器仍然有效。
  • 如果你需要的元素的数组,你必须建立一个新的,他们都添加到它,因为没有基本的阵列。

在一般情况下,使用时你不在乎什么类型的,你正在使用顺序容器的载体,但如果你正在做许多插入或擦除并从端部以外的任何地方的容器,你会想使用名单。 或者,如果你需要随机访问,那么你会希望载体,而不是名单。 除此之外,还有自然,你会需要一个或者根据您的应用程序等,但总体而言,这些都是很好的指导实例。



Answer 3:

如果您不需要插入元素的时候则载体的效率会更高。 它具有更好的CPU缓存局部性比列表。 换句话说,访问一个元件使得它可能是下一个元素是存在于高速缓存和可以在不必读取慢RAM检索。



Answer 4:

大多数的答案在这里错过了一个重要的细节:什么?

那你想保持在containter?

如果它是一个集合int S,然后std::list将在每一个场景中输了,无论你是否能重新分配,你只能从前面卸下,等列表是慢遍历,每次插入你的成本与分配器的相互作用。 这将是非常难以制备例如,在list<int>跳动vector<int> 。 即使如此, deque<int>可能会更好或关闭,不justyfing使用清单,这将有更大的内存开销。

但是,如果你正在处理大量数据的,丑陋的斑点 - 和他们几个人 - 你不想插入时overallocate和复制由于重新分配将是一场灾难 - 那么你可以,也许,是一个更好list<UglyBlob>vector<UglyBlob>

不过,如果切换到vector<UglyBlob*>甚至vector<shared_ptr<UglyBlob> >再次-列表将会落后。

因此,访问模式,目标元素计数等仍然影响的比较,但在我看来 - 元素大小 - 复制等成本



Answer 5:

的std ::列表中的一个特殊的功能,是拼接(连接或移动的部分或整个列表到不同的列表)。

又或者,如果你的内容复制非常昂贵。 在它可能会更便宜这样的情况下,例如,排序与列表集合。

还要注意的是,如果集合是小(内容不复制特别贵),矢量仍可能跑赢大盘列表,即使你插入和删除任何地方。 清单单独分配每个节点,这可能会远远超过走动几个简单的物体更昂贵。

我不认为有很硬性规则。 这取决于你最想做到与容器,以及你希望怎样大的容器中和所包含的类型。 载体通常胜过列表,因为分配其内容作为单个连续块(它基本上是一个动态分配的阵列,并且在大多数情况下的阵列是保持一堆东西的最有效的方式)。



Answer 6:

那么我的课的学生们显得相当无力时,它是更有效的使用载体向我解释,但我建议使用清单时,他们看起来很高兴。

这是我的理解

列表 :每个项目包含一个地址到下一个或前一个元素,所以用这个功能,你可以随机的物品,即使它们没有排序,顺序不会改变:它是有效的,如果你的内存碎片。 但它也有一个其他非常大的优势:你可以很容易地插入/删除项目,因为你需要做的唯一的事情就是改变一些指点。 缺点:要读取一个随机的单个项目,你有,直到你找到正确的地址,从一个项目跳到另一个。

载体 :当使用载体,所述存储器被更加有组织像规则阵列:每个第n个项目只是第(n-1)个项目后和前(N + 1)个项目被存储。 为什么它比列表更好? 因为它允许快速随机访问。 下面是如何:如果你知道一个矢量项目的大小,如果他们是在内存中连续的,你可以很容易地预测,其中第n个产品; 你没有浏览列表中的所有项目改为你想要的,与向量,就直接读取,使用名单你不能。 在另一方面,修改矢量阵列或改变一个值是更慢。

列表是更合适的,以保持其可以加入/在存储器中去除的目标轨道。 当你想从单一项目的大批量访问一个元素的载体是比较合适的。

我不知道名单是如何优化,但你要知道,如果你想快速读取访问,你应该使用矢量,因为STL有多好固定列表,它不会比读向量访问一样快。



Answer 7:

基本上是一个向量是具有自动存储器管理的阵列。 数据在存储器中连续。 尝试在中间插入的数据是一项昂贵的操作。

在列表中的数据存储在内存无关位置。 在中间插入不涉及拷贝一些数据,以腾出空间给新的。

要回答更具体你的问题,我会引用此页面

载体通常是最有效的时间用于访问元素和添加或删除的元素从所述序列的结束。 对于涉及插入或在端部以外的位置删除元素的操作,他们的表现比双端并列出恶化,有不太一致的迭代器和比列表的引用。



Answer 8:

任何时候你不能有无效的迭代器。



Answer 9:

当你在序列的中间很多插入或缺失。 如内存管理器。



Answer 10:

保留迭代器的有效性是一个理由使用一个列表。 另一种是当你不想要一个矢量推进项目时重新分配。 这可以通过巧妙运用储备()进行管理,但在某些情况下,它可能会更容易或更可行只使用一个列表。



Answer 11:

如果要移动的容器之间的物体时,可以使用list::splice

例如,一个图形分割算法可以具有对象的恒定数量越来越多的容器中递归地分割。 该对象应初始化一次,并始终保持在内存中的相同位置。 它的速度更快比通过重新分配重新链接重新排列。

编辑:如库准备实施的C ++ 0x,拼接的一般情况的子序列到一个列表是变线性与序列的长度的复杂性。 这是因为splice (现在)需要遍历序列来计算它的元素个数。 (由于列表需要记录其大小。)简单计数和重新链接列表仍然快于任何替代,和拼接整个列表或单个元素是特殊的情况下具有恒定的复杂性。 但是,如果你有很长的序列拼接,您可能需要周围挖一个更好的,老式的,不符合规定的容器。



Answer 12:

其中唯一的硬规则list必须使用是你需要的指针分发到容器的元素。

不像vector ,你知道元素的内存不会被重新分配。 如果可以,那么你可能有一个指针到未使用的内存,这充其量是一个很大的禁忌,在最坏的一个SEGFAULT

(技术上来说, vector*_ptr也将工作,但在这种情况下,你是模仿list ,这样只是语义。)

其它软规则与插入元素的容器中间的可能性能问题做,于是list将是可取的。



文章来源: vector vs. list in STL