[英]std::vector versus std::array in C++
What are the difference between a std::vector
and an std::array
in C++? C++ 中的
std::vector
和std::array
有什么区别? When should one be preferred over another?什么时候应该优先考虑另一个? What are the pros and cons of each?
各自的优缺点是什么? All my textbook does is list how they are the same.
我的教科书所做的就是列出它们的相同之处。
std::vector
is a template class that encapsulate a dynamic array 1 , stored in the heap, that grows and shrinks automatically if elements are added or removed. std::vector
是一个模板类,它封装了一个动态数组1 ,存储在堆中,如果添加或删除元素,它会自动增长和收缩。 It provides all the hooks ( begin()
, end()
, iterators, etc) that make it work fine with the rest of the STL.它提供了所有钩子(
begin()
、 end()
、迭代器等),使其与 STL 的其余部分一起正常工作。 It also has several useful methods that let you perform operations that on a normal array would be cumbersome, like eg inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes).它还有几个有用的方法,可以让您在普通数组上执行繁琐的操作,例如在向量中间插入元素(它处理在幕后移动以下元素的所有工作)。
Since it stores the elements in memory allocated on the heap, it has some overhead in respect to static arrays.由于它将元素存储在堆上分配的内存中,因此相对于静态数组有一些开销。
std::array
is a template class that encapsulate a statically-sized array, stored inside the object itself, which means that, if you instantiate the class on the stack, the array itself will be on the stack. std::array
是一个模板类,它封装了一个静态大小的数组,存储在对象本身内部,这意味着,如果在堆栈上实例化该类,则数组本身将在堆栈上。 Its size has to be known at compile time (it's passed as a template parameter), and it cannot grow or shrink.它的大小必须在编译时知道(它作为模板参数传递),并且它不能增长或缩小。
It's more limited than std::vector
, but it's often more efficient, especially for small sizes, because in practice it's mostly a lightweight wrapper around a C-style array.它比
std::vector
更受限制,但它通常更有效,尤其是对于小尺寸,因为实际上它主要是围绕 C 样式数组的轻量级包装器。 However, it's more secure, since the implicit conversion to pointer is disabled, and it provides much of the STL-related functionality of std::vector
and of the other containers, so you can use it easily with STL algorithms & co.但是,它更安全,因为禁用了对指针的隐式转换,并且它提供了
std::vector
和其他容器的许多 STL 相关功能,因此您可以轻松地将它与 STL 算法和合作一起使用。 Anyhow, for the very limitation of fixed size it's much less flexible than std::vector
.无论如何,对于固定大小的限制,它比
std::vector
灵活得多。
For an introduction to std::array
, have a look at this article ;有关
std::array
的介绍,请查看这篇文章; for a quick introduction to std::vector
and to the the operations that are possible on it, you may want to look at its documentation .要快速介绍
std::vector
及其可能的操作,您可能需要查看其文档。
To emphasize a point made by @MatteoItalia, the efficiency difference is where the data is stored.为了强调@MatteoItalia 提出的观点,效率差异在于数据的存储位置。 Heap memory (required with
vector
) requires a call to the system to allocate memory and this can be expensive if you are counting cycles.堆内存(
vector
需要)需要调用系统来分配内存,如果您正在计算周期,这可能会很昂贵。 Stack memory (possible for array
) is virtually "zero-overhead" in terms of time, because the memory is allocated by just adjusting the stack pointer and it is done just once on entry to a function.堆栈内存(可能用于
array
)在时间方面实际上是“零开销”,因为内存是通过调整堆栈指针分配的,并且在进入函数时只完成一次。 The stack also avoids memory fragmentation.堆栈还避免了内存碎片。 To be sure,
std::array
won't always be on the stack;可以肯定的是,
std::array
不会总是在堆栈中; it depends on where you allocate it, but it will still involve one less memory allocation from the heap compared to vector.这取决于你在哪里分配它,但与向量相比,它仍然会从堆中分配更少的内存。 If you have a
如果你有一个
definitely use a std::array
over a vector.绝对在向量上使用
std::array
。 If any of those requirements is not true, then use a std::vector
.如果这些要求中的任何一个不正确,则使用
std::vector
。
Using the std::vector<T>
class:使用
std::vector<T>
类:
...is just as fast as using built-in arrays, assuming you are doing only the things built-in arrays allow you to do (read and write to existing elements). ...就像使用内置数组一样快,假设您只做内置数组允许您做的事情(读取和写入现有元素)。
...automatically resizes when new elements are inserted. ...插入新元素时自动调整大小。
...allows you to insert new elements at the beginning or in the middle of the vector, automatically "shifting" the rest of the elements "up"( does that make sense?). ...允许您在向量的开头或中间插入新元素,自动“向上”“移动”其余元素(这是否有意义?)。 It allows you to remove elements anywhere in the
std::vector
, too, automatically shifting the rest of the elements down.它也允许您删除
std::vector
任何位置的元素,自动将其余元素向下移动。
...allows you to perform a range-checked read with the at()
method (you can always use the indexers []
if you don't want this check to be performed). ...允许您使用
at()
方法执行范围检查读取at()
如果您不想执行此检查,您始终可以使用索引器[]
)。
There are
two
three main caveats to using std::vector<T>
:使用
std::vector<T>
有
两个
三个主要警告:
You don't have reliable access to the underlying pointer, which may be an issue if you are dealing with third-party functions that demand the address of an array.您无法可靠地访问底层指针,如果您正在处理需要数组地址的第三方函数,这可能是一个问题。
The std::vector<bool>
class is silly. std::vector<bool>
类很愚蠢。 It's implemented as a condensed bitfield, not as an array.它被实现为一个压缩位域,而不是一个数组。 Avoid it if you want an array of
bool
s!如果您想要一个
bool
数组,请避免使用它!
During usage, std::vector<T>
s are going to be a bit larger than a C++ array with the same number of elements.在使用过程中,
std::vector<T>
将比具有相同元素数量的 C++ 数组大一点。 This is because they need to keep track of a small amount of other information, such as their current size, and because whenever std::vector<T>
s resize, they reserve more space then they need.这是因为它们需要跟踪少量其他信息,例如它们的当前大小,并且因为每当
std::vector<T>
调整大小时,它们都会保留比所需更多的空间。 This is to prevent them from having to resize every time a new element is inserted.这是为了防止它们每次插入新元素时都必须调整大小。 This behavior can be changed by providing a custom
allocator
, but I never felt the need to do that!这种行为可以通过提供自定义
allocator
来改变,但我从来没有觉得有必要这样做!
Edit: After reading Zud's reply to the question, I felt I should add this:编辑:阅读 Zud 对问题的回复后,我觉得我应该添加以下内容:
The std::array<T>
class is not the same as a C++ array. std::array<T>
类与 C++ 数组不同。 std::array<T>
is a very thin wrapper around C++ arrays, with the primary purpose of hiding the pointer from the user of the class (in C++, arrays are implicitly cast as pointers, often to dismaying effect). std::array<T>
是 C++ 数组的一个非常薄的包装器,主要目的是向类的用户隐藏指针(在 C++ 中,数组被隐式转换为指针,通常会产生令人沮丧的效果)。 The std::array<T>
class also stores its size (length), which can be very useful. std::array<T>
类还存储其大小(长度),这非常有用。
If you are considering using multidimensional arrays, then there is one additional difference between std::array and std::vector.如果您正在考虑使用多维数组,那么 std::array 和 std::vector 之间还有一个额外的区别。 A multidimensional std::array will have the elements packed in memory in all dimensions, just as ac style array is.
多维 std::array 会将所有维度的元素打包在内存中,就像 ac 样式数组一样。 A multidimensional std::vector will not be packed in all dimensions.
多维 std::vector 不会在所有维度上打包。
Given the following declarations:鉴于以下声明:
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]
A pointer to the first element in the c-style array (cConc) or the std::array (aConc) can be iterated through the entire array by adding 1 to each preceding element.指向 c 样式数组 (cConc) 或 std::array (aConc) 中第一个元素的指针可以通过向每个前面的元素加 1 来遍历整个数组。 They are tightly packed.
它们被紧紧地包裹着。
A pointer to the first element in the vector array (vConc) or the pointer array (ptrConc) can only be iterated through the first 5 (in this case) elements, and then there are 12 bytes (on my system) of overhead for the next vector.指向向量数组 (vConc) 或指针数组 (ptrConc) 中第一个元素的指针只能迭代前 5 个(在本例中)元素,然后有 12 个字节(在我的系统上)用于下一个向量。
This means that a std::vector> array initialized as a [3][1000] array will be much smaller in memory than one initialized as a [1000][3] array, and both will be larger in memory than a std:array allocated either way.这意味着初始化为 [3][1000] 数组的 std::vector> 数组在内存中将比初始化为 [1000][3] 数组的数组小得多,并且两者在内存中都比 std 大:以任何一种方式分配的数组。
This also means that you can't simply pass a multidimensional vector (or pointer) array to, say, openGL without accounting for the memory overhead, but you can naively pass a multidimensional std::array to openGL and have it work out.这也意味着您不能简单地将多维向量(或指针)数组传递给 openGL,而不考虑内存开销,但您可以天真地将多维 std::array 传递给 openGL 并使其解决。
Summarizing the above discussion in a table for quick reference:将上述讨论总结在一个表格中以供快速参考:
C-Style Array ![]() |
std::array![]() |
std::vector![]() |
|
---|---|---|---|
Size![]() |
Fixed/Static![]() |
Fixed/Static![]() |
Dynamic![]() |
Memory efficiency![]() |
More efficient![]() |
More Efficient![]() |
Less efficient![]() (May double its size on new allocation.) ![]() |
Copying![]() |
Iterate over elements![]() or use std::copy() ![]() |
Direct copy: a2 = a1;![]() |
Direct copy: v2 = v1;![]() |
Passing to function![]() |
Passed by pointer.![]() (Size not available in function) ![]() |
Passed by value![]() |
Passed by value![]() (Size available in that function) ![]() |
Size![]() |
sizeof(a1) / sizeof(a1[0]) ![]() |
a1.size() ![]() |
v1.size() ![]() |
Use case![]() |
For quick access and when![]() insertions/deletions not frequently needed. ![]() |
Same as classic array but![]() safer and easier to pass and copy. ![]() |
When frequent additions or![]() deletions might be needed ![]() |
向量是容器类,而数组是分配的内存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.