c++中std::vector和std::array的区别是什么?什么时候应该优先选择一个?它们各自的优点和缺点是什么?我的课本只列出了它们的相同之处。
std::vector
std::array
vector是容器类,而array是已分配的内存。
std::vector是一个模板类,它封装了一个动态数组__abc3,存储在堆中,在添加或删除元素时自动增长或缩小。它提供了所有的钩子(begin(), end(),迭代器等),使其与STL的其余部分正常工作。它还有几个有用的方法,可以让你执行在普通数组上很麻烦的操作,比如在向量中间插入元素(它处理了幕后移动以下元素的所有工作)。
begin()
end()
由于它将元素存储在堆上分配的内存中,因此相对于静态数组,它有一些开销。
std::array是一个模板类,它封装了一个静态大小的数组,存储在对象本身内部,这意味着,如果你在堆栈上实例化类,数组本身将在堆栈上。它的大小必须在编译时已知(它作为模板参数传递),并且它不能增长或缩小。
它比std::vector更有限制,但它通常更有效,特别是对于较小的大小,因为在实践中它主要是c风格数组的轻量级包装器。然而,它更安全,因为指针的隐式转换被禁用了,并且它提供了std::vector和其他容器的许多与STL相关的功能,所以你可以很容易地将它与STL算法一起使用。无论如何,由于固定大小的限制,它比std::vector灵活得多。
有关std::array的介绍,请查看这篇文章;要快速介绍std::vector及其上可能的操作,你可能想要查看它的文档。
使用std::vector<T>类:
std::vector<T>
...Is 和使用内置数组一样快,假设您只做内置数组允许您做的事情(读取和写入现有元素)。
...插入新元素时自动调整大小。
...允许你插入新的元素在开始或在中间的向量,自动“移动”其余的元素“向上”(这有意义吗?)它还允许你删除std::vector中的任何位置的元素,自动向下移动其余的元素。
...允许你使用at()方法执行范围检查读取(如果你不希望执行这个检查,你总是可以使用索引器[])。
at()
[]
使用std::vector<T>有三个主要的注意事项:
您没有对底层指针的可靠访问,如果您正在处理需要数组地址的第三方函数,则可能是一个问题。
std::vector<bool>类很愚蠢。它被实现为一个压缩的位域,而不是数组。如果你想要一个__abc1数组,请避免使用它!
std::vector<bool>
在使用过程中,__abc0将比具有相同数量元素的c++数组略大。这是因为它们需要跟踪少量的其他信息,例如它们的当前大小,并且因为每当__abc0调整大小时,它们会保留比所需的更多空间。这是为了防止每次插入新元素时都必须调整大小。这种行为可以通过提供自定义allocator来改变,但我从未觉得有必要这样做!
allocator
编辑:在阅读了Zud对这个问题的回复后,我觉得我应该加上这个:
std::array<T>类与c++数组不同。std::array<T>是c++数组的一个非常薄的包装器,主要目的是对类的用户隐藏指针(在c++中,数组被隐式转换为指针,通常会产生令人沮丧的效果)。std::array<T>类还存储它的大小(长度),这非常有用。
std::array<T>
为了强调@MatteoItalia提出的观点,效率差异在于数据存储的位置。堆内存(vector需要)需要调用系统来分配内存,如果你在计算周期,这可能是昂贵的。就时间而言,堆栈内存(可能用于array)实际上是“零开销”的,因为内存是通过调整堆栈指针分配的,并且只在函数进入时执行一次。堆栈还避免了内存碎片。可以肯定的是,std::array并不总是在堆栈上;这取决于你在哪里分配它,但与vector相比,它仍然会从堆中少分配一个内存。如果你有
vector
array
在vector上使用std::array。如果这些要求中的任何一个不是真的,那么使用std::vector。
如果您正在考虑使用多维数组,那么std::array和std::vector之间还有一个额外的区别。多维std::array将所有维度的元素都打包在内存中,就像c风格的数组一样。多维std::向量不会被包装在所有维度中。
给定以下声明:
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个字节(在我的系统中)用于下一个矢量。
这意味着初始化为[3][1000]数组的std::vector>数组在内存中比初始化为[1000][3]数组的要小得多,并且两者在内存中都比以任何一种方式分配的std:array大。
这也意味着您不能简单地将多维向量(或指针)数组传递给openGL而不考虑内存开销,但是您可以简单地将多维std::数组传递给openGL并让它工作。
将上述讨论总结为表格,以供快速参考: