C++中的std::vector和std::array有什么区别?什么时候一个人应该优先于另一个人?每种方法的优缺点是什么?我的教科书只是列出它们是如何相同的。
std::vector
std::array
tp5buhyn1#
std::vector是一个模板类,它封装了一个动态数组1,存储在堆中,如果添加或删除元素,它会自动增长和收缩。它提供了所有的钩子(begin(),end(),迭代器等),使其与STL的其余部分一起工作。它还有几个有用的方法,可以让您执行在普通数组上很麻烦的操作,如e。g.在向量中间插入元素(它处理将后面的元素移动到幕后的所有工作)。由于它将元素存储在堆上分配的内存中,因此它在静态数组方面有一些开销。std::array是一个模板类,它封装了一个静态大小的数组,存储在对象本身中,这意味着,如果在堆栈上示例化该类,则数组本身将在堆栈上。它的大小必须在编译时已知(它作为模板参数传递),并且它不能增长或收缩。它比std::vector有更多的限制,但它通常更有效,特别是对于小尺寸,因为在实践中,它主要是C风格数组的轻量级 Package 器。但是,它更安全,因为禁用了到指针的隐式转换,并且它提供了std::vector和其他容器的许多STL相关功能,因此您可以轻松地将其与STL算法& co.无论如何,由于固定大小的限制,它的灵活性远远低于std::vector。有关std::array的介绍,请参阅this article;要快速了解std::vector及其上可能的操作,您可能需要查看它的documentation。1.实际上,我认为在标准中,它们是根据不同操作的最大复杂性来描述的(e.例如,在恒定时间内的随机访问、在线性时间内对所有元素的迭代、在恒定摊销时间内在末尾添加和移除元素等),但是除了使用动态数组之外,没有其他方法来满足这样的要求。正如@Lucretiel所述,标准实际上要求元素连续存储,因此 *it是 * 一个动态数组,存储在相关分配器放置的位置。
begin()
end()
nafvub8i2#
为了强调@MatteoItalia提出的一个观点,效率差异在于数据存储的位置。堆内存(vector需要)需要调用系统来分配内存,如果您计算周期,这可能会很昂贵。堆栈内存(可能用于array)在时间方面实际上是“零开销”,因为内存只通过调整堆栈指针来分配,并且在进入函数时只执行一次。堆栈还可以避免内存碎片。可以肯定的是,std::array并不总是在堆栈上;这取决于你在哪里分配它,但与vector相比,它仍然会少涉及一个来自堆的内存分配。如果你有一个
vector
array
一定要在向量上使用std::array。如果这些要求中的任何一个不成立,则使用std::vector。
sg3maiej3#
在表格中总结上述讨论,以供快速参考:| | C型阵列|std::move_iterator|std::vector|| --------------|--------------|--------------|--------------|| 尺寸|固定/静态|固定/静态|动态|| 存储器效率|效率更高|更高效|效率较低(可能会在新的分配中增加一倍。)|| 复制|迭代元素使用std::copy()|直接拷贝:a2 = a1;|直接拷贝:v2 = v1;|| 传递给函数|通过指针传递。(功能中未提供尺寸)|按值传递|按值传递(该功能中可用的大小)|| 尺寸|sizeof(a1)/ sizeof(a1[0])|a1.size()|v1.size()|| 使用案例|用于快速访问以及何时不经常需要插入/删除。|与经典数组相同,但更安全、更容易传递和复制。|当频繁添加或可能需要删除|
n3ipq98p4#
如果您正在考虑使用多维数组,那么std::array和std::vector之间还有一个额外的区别。多维std::array将所有维度的元素打包在内存中,就像C风格的数组一样。多维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个字节的开销(在我的系统上)。这意味着一个初始化为[3][1000]数组的std::vector<std::vector<int>>数组在内存中比初始化为[1000][3]数组的std::vector<std::vector<int>>数组要小得多,并且两者在内存中都比以任何方式分配的std::array大。这也意味着你不能简单地将一个多维向量(或指针)数组传递给OpenGL而不考虑内存开销,但是你可以简单地将一个多维std::array传递给OpenGL并让它工作。
[3][1000]
std::vector<std::vector<int>>
[1000][3]
xt0899hw5#
使用std::vector<T>类:
std::vector<T>
at()
[]
使用std::vector<T>有三个主要注意事项:1.你没有对底层指针的可靠访问,如果你正在处理需要数组地址的第三方函数,这可能是一个问题。
std::vector<bool>
bool
allocator
std::array<T>
ve7v8dk26#
向量是一个容器类,而数组是一个分配的内存。
6条答案
按热度按时间tp5buhyn1#
std::vector
是一个模板类,它封装了一个动态数组1,存储在堆中,如果添加或删除元素,它会自动增长和收缩。它提供了所有的钩子(begin()
,end()
,迭代器等),使其与STL的其余部分一起工作。它还有几个有用的方法,可以让您执行在普通数组上很麻烦的操作,如e。g.在向量中间插入元素(它处理将后面的元素移动到幕后的所有工作)。由于它将元素存储在堆上分配的内存中,因此它在静态数组方面有一些开销。
std::array
是一个模板类,它封装了一个静态大小的数组,存储在对象本身中,这意味着,如果在堆栈上示例化该类,则数组本身将在堆栈上。它的大小必须在编译时已知(它作为模板参数传递),并且它不能增长或收缩。它比
std::vector
有更多的限制,但它通常更有效,特别是对于小尺寸,因为在实践中,它主要是C风格数组的轻量级 Package 器。但是,它更安全,因为禁用了到指针的隐式转换,并且它提供了std::vector
和其他容器的许多STL相关功能,因此您可以轻松地将其与STL算法& co.无论如何,由于固定大小的限制,它的灵活性远远低于std::vector
。有关
std::array
的介绍,请参阅this article;要快速了解std::vector
及其上可能的操作,您可能需要查看它的documentation。1.实际上,我认为在标准中,它们是根据不同操作的最大复杂性来描述的(e.例如,在恒定时间内的随机访问、在线性时间内对所有元素的迭代、在恒定摊销时间内在末尾添加和移除元素等),但是除了使用动态数组之外,没有其他方法来满足这样的要求。正如@Lucretiel所述,标准实际上要求元素连续存储,因此 *it是 * 一个动态数组,存储在相关分配器放置的位置。
nafvub8i2#
为了强调@MatteoItalia提出的一个观点,效率差异在于数据存储的位置。堆内存(
vector
需要)需要调用系统来分配内存,如果您计算周期,这可能会很昂贵。堆栈内存(可能用于array
)在时间方面实际上是“零开销”,因为内存只通过调整堆栈指针来分配,并且在进入函数时只执行一次。堆栈还可以避免内存碎片。可以肯定的是,std::array
并不总是在堆栈上;这取决于你在哪里分配它,但与vector相比,它仍然会少涉及一个来自堆的内存分配。如果你有一个一定要在向量上使用
std::array
。如果这些要求中的任何一个不成立,则使用std::vector
。sg3maiej3#
在表格中总结上述讨论,以供快速参考:
| | C型阵列|std::move_iterator|std::vector|
| --------------|--------------|--------------|--------------|
| 尺寸|固定/静态|固定/静态|动态|
| 存储器效率|效率更高|更高效|效率较低(可能会在新的分配中增加一倍。)|
| 复制|迭代元素使用std::copy()|直接拷贝:a2 = a1;|直接拷贝:v2 = v1;|
| 传递给函数|通过指针传递。(功能中未提供尺寸)|按值传递|按值传递(该功能中可用的大小)|
| 尺寸|sizeof(a1)/ sizeof(a1[0])|a1.size()|v1.size()|
| 使用案例|用于快速访问以及何时不经常需要插入/删除。|与经典数组相同,但更安全、更容易传递和复制。|当频繁添加或可能需要删除|
n3ipq98p4#
如果您正在考虑使用多维数组,那么
std::array
和std::vector
之间还有一个额外的区别。多维std::array
将所有维度的元素打包在内存中,就像C风格的数组一样。多维std::vector
不会在所有维度中打包。给定以下声明:
指向C样式数组(cConc)或
std::array
(aConc)中第一个元素的指针可以通过向前面的每个元素加1来遍历整个数组。它们被紧紧地包裹着。指向向量数组(vConc)或指针数组(ptrConc)中第一个元素的指针只能迭代前5个元素(在本例中),然后下一个向量有12个字节的开销(在我的系统上)。
这意味着一个初始化为
[3][1000]
数组的std::vector<std::vector<int>>
数组在内存中比初始化为[1000][3]
数组的std::vector<std::vector<int>>
数组要小得多,并且两者在内存中都比以任何方式分配的std::array
大。这也意味着你不能简单地将一个多维向量(或指针)数组传递给OpenGL而不考虑内存开销,但是你可以简单地将一个多维
std::array
传递给OpenGL并让它工作。xt0899hw5#
使用
std::vector<T>
类:std::vector
中的任何元素,自动向下移动其余元素。at()
方法执行范围检查读取(如果您不希望执行此检查,则始终可以使用索引器[]
)。使用
std::vector<T>
有三个主要注意事项:1.你没有对底层指针的可靠访问,如果你正在处理需要数组地址的第三方函数,这可能是一个问题。
std::vector<bool>
类是愚蠢的。它被实现为一个压缩位域,而不是一个数组。如果你想要一个bool
的数组,请避免使用它!1.在使用过程中,
std::vector<T>
s将比具有相同元素数的C数组大一点。这是因为它们需要跟踪少量的其他信息,例如它们的当前大小,并且因为每当std::vector<T>
调整大小时,它们都会保留比所需更多的空间。这是为了防止每次插入新元素时都必须调整其大小。这种行为可以通过提供一个自定义的allocator
来改变,但我从来没有觉得有必要这样做!编辑:在阅读了Zud对这个问题的回复后,我觉得我应该补充一下:
std::array<T>
类与C数组不同。std::array<T>
是一个非常薄的C数组 Package 器,主要目的是对类的用户隐藏指针(在C中,数组被隐式转换为指针,通常会产生令人沮丧的效果)。std::array<T>
类还存储其大小(长度),这非常有用。ve7v8dk26#
向量是一个容器类,而数组是一个分配的内存。