在C ++中std :: vector与std :: array

C ++中std::vectorstd::array有什么区别? 什么时候应该比另一个更受欢迎? 各有什么优点和缺点? 我所有的教科书都列出了他们是如何相同的。

std::vector是一个模板类,它封装了一个存储在堆中的dynamic数组1 ,如果元素被添加或删除,它将自动增长和缩小。 它提供了所有的钩子( begin()end() ,迭代器等),使其与STL的其余部分一起工作。 它还有几个有用的方法可以让你执行在普通数组上的操作,比如在向量中间插入元素(它处理在后台移动后面元素的所有工作)。

由于它将这些元素存储在堆中分配的内存中,所以它在静态数组方面有一些开销。

std::array是一个模板类,它封装了一个静态大小的数组,存储在对象本身内部,这意味着,如果您在堆栈上实例化类,则数组本身将位于堆栈上。 它的大小必须在编译时已知(它作为模板parameter passing),它不能增长或缩小。

它比std::vector更有限,但是它通常更有效率,特别是对于小尺寸,因为实际上它大多是围绕C风格的数组的轻量级包装。 但是,它更安全,因为隐式转换为指针是禁用的,它提供了std::vector和其他容器的很多STL相关的function,所以你可以很容易地使用STLalgorithm&co。 无论如何,对于固定大小的限制,它比std::vector更不灵活。

有关std::array的介绍,请看这篇文章 ; 对于std::vector以及其上可能的操作的快速介绍,您可能需要查看它的文档 。


  1. 实际上,我认为在标准中它们是根据不同操作的最大复杂度来描述的(例如,随机访问在固定时间内,在线性时间内迭代所有元素,在固定的分摊时间内增加和删除元素,等等),但AFAIK除了使用dynamic数组之外没有其他方法可以满足这些要求。 正如@Lucretiel所说,标准实际上要求元素是连续存储的,所以它是一个dynamic数组,存储在关联的分配器放置的地方。

使用std::vector<T>类:

  • …就像使用内置数组一样快 ,假设你只做内置数组允许你做的事情(读写现有元素)。

  • …在插入新元素时自动resize。

  • …允许你在vector的开头或者中间插入新的元素,自动地将剩下的元素“上移”(这是否合理?)。 它允许您删除std::vector任何位置的元素,并自动将其余元素向下移动。

  • …允许您使用at()方法执行范围检查读取at()如果不希望执行此检查,则始终可以使用索引器[] )。

两个三个主要的警告使用std::vector<T>

  1. 您没有可靠的底层指针访问权限,如果您要处理需要数组地址的第三方函数,这可能是一个问题。

  2. std::vector<bool>类是愚蠢的。 它是作为一个精简的位域来实现的,而不是一个数组。 避免它,如果你想要一个bool的数组!

  3. 在使用过程中, std::vector<T>将比具有相同元素数量的C ++数组大一点。 这是因为他们需要跟踪less量的其他信息,比如他们当前的大小,因为每当std::vector<T>resize,他们就会预留更多的空间。 这是为了防止他们每次插入新元素时都要resize。 这种行为可以通过提供一个自定义的allocator来改变,但我从来没有觉得需要这样做!


编辑:在阅读祖德对这个问题的答复后,我觉得我应该补充一点:

std::array<T>类与C ++数组不同。 std::array<T>是C ++数组的一个非常薄的包装,其主要目的是隐藏类的用户的指针(在C ++中,数组隐含地转换为指针,往往会造成影响)。 std::array<T>类也存储它的大小(长度),这可能非常有用。

为了强调@MatteoItalia提出的一个观点,效率差异是数据存储的地方。 堆内存( vector需要)需要调用系统来分配内存,如果要计算周期,则这可能很昂贵。 堆栈内存(可能是array )在时间上实际上是“零开销的”,因为内存是通过调整堆栈指针来分配的,而且在进入一个函数时只需要完成一次。 该堆栈还可以避免内存碎片。 可以肯定的是, std::array并不总是在堆栈上; 这取决于你在哪里分配它,但是与vector相比,它仍然会涉及less量的堆内存分配。 如果你有一个

  • 小的“数组”(小于100个元素) – (一个典型的堆栈大约是8MB,所以不要在堆栈上分配超过几KB的值,或者如果你的代码是recursion的,
  • 大小将被固定
  • 生命周期在函数范围内(或者是与父类具有相同生命周期的成员值)
  • 你正在计算周期,

绝对使用一个向量的std::array 。 如果任何这些要求是不正确的,然后使用一个std::vector

如果你正在考虑使用multidimensional array,那么在std :: array和std :: vector之间还有一个额外的区别。 一个多维的std ::数组将会在所有维度中将内容打包在内存中,就像ac风格的数组一样。 多维的std :: vector将不会被打包在所有维度中。

鉴于以下声明:

 int cConc[3][5]; std::array<std::array<int, 5>, 3> aConc; int **ptrConc; // initialized to [3][5] via new and destructed via delete std::vector<std::vector<int>> vConc; // initialized to [3][5] 

指向c样式数组(cConc)或std :: array(aConc)中第一个元素的指针可以通过在每个前面的元素上加1来迭代整个数组。 他们紧紧包装。

向量数组(vConc)或指针数组(ptrConc)中的第一个元素的指针只能通过前5个(本例中)元素迭代,然后有12个字节(在我的系统上)下一个vector。

这意味着初始化为[3] [1000]数组的std :: vector>数组在内存中比初始化为[1000] [3]数组的内存要小得多,并且两者在内存中的比std:数组分配的方式。

这也意味着你不能简单地将一个多维向量(或指针)数组传递给openGL,而不考虑内存开销,但你可以天真地传递一个多维的std ::数组到OpenGL并使其工作。

vector对数组的一个优点是可以使用vector_name.size()来查找vector的当前大小

正如你可以想象的,这可以在各种情况下非常有用,你可以很容易地获取array_list中的元素数量。

vector是一个容器类,而一个数组是分配的内存。