在C ++中std :: vector与std :: array
C ++中std::vector
和std::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
以及其上可能的操作的快速介绍,您可能需要查看它的文档 。
-
实际上,我认为在标准中它们是根据不同操作的最大复杂度来描述的(例如,随机访问在固定时间内,在线性时间内迭代所有元素,在固定的分摊时间内增加和删除元素,等等),但AFAIK除了使用dynamic数组之外没有其他方法可以满足这些要求。正如@Lucretiel所说,标准实际上要求元素是连续存储的,所以它是一个dynamic数组,存储在关联的分配器放置的地方。
使用std::vector<T>
类:
-
…就像使用内置数组一样快 ,假设你只做内置数组允许你做的事情(读写现有元素)。
-
…在插入新元素时自动resize。
-
…允许你在vector的开头或者中间插入新的元素,自动地将剩下的元素“上移”(这是否合理?)。 它允许您删除
std::vector
任何位置的元素,并自动将其余元素向下移动。 -
…允许您使用
at()
方法执行范围检查读取at()
如果不希望执行此检查,则始终可以使用索引器[]
)。
有两个三个主要的警告使用std::vector<T>
:
-
您没有可靠的底层指针访问权限,如果您要处理需要数组地址的第三方函数,这可能是一个问题。
-
std::vector<bool>
类是愚蠢的。 它是作为一个精简的位域来实现的,而不是一个数组。 避免它,如果你想要一个bool
的数组! -
在使用过程中,
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是一个容器类,而一个数组是分配的内存。