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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4424579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:22:48  来源:igfitidea点击:

std::vector versus std::array in C++

c++arraysvector

提问by Zud

What are the difference between a std::vectorand an std::arrayin C++? 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.

C++中的astd::vector和an有什么区别std::array?什么时候应该优先考虑另一个?各自的优缺点是什么?我的教科书所做的就是列出它们的相同之处。

回答by Matteo Italia

std::vectoris a template class that encapsulate a dynamic array1, stored in the heap, that grows and shrinks automatically if elements are added or removed. It provides all the hooks (begin(), end(), iterators, etc) that make it work fine with the rest of the STL. It also has several useful methods that let you perform operations that on a normal array would be cumbersome, like e.g. inserting elements in the middle of a vector (it handles all the work of moving the following elements behind the scenes).

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

Since it stores the elements in memory allocated on the heap, it has some overhead in respect to static arrays.

由于它将元素存储在堆上分配的内存中,因此相对于静态数组有一些开销。

std::arrayis 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. Its size has to be known at compile time (it's passed as a template parameter), and it cannot grow or shrink.

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

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. However, it's more secure, since the implicit conversion to pointer is disabled, and it provides much of the STL-related functionality of std::vectorand of the other containers, so you can use it easily with STL algorithms & co. Anyhow, for the very limitation of fixed size it's much less flexible than std::vector.

它比 更受限制std::vector,但通常更有效,尤其是对于小尺寸,因为实际上它主要是围绕 C 样式数组的轻量级包装器。但是,它更安全,因为禁用了对指针的隐式转换,并且它提供std::vector了其他容器和其他容器的许多 STL 相关功能,因此您可以轻松地将它与 STL 算法一起使用。无论如何,对于固定大小的限制,它比std::vector.

For an introduction to std::array, have a look at this article; for a quick introduction to std::vectorand to the the operations that are possible on it, you may want to look at its documentation.

有关介绍std::array,请看这篇文章;要快速介绍std::vector和了解其上可能的操作,您可能需要查看其文档



  1. Actually, I think that in the standard they are described in terms of maximum complexity of the different operations (e.g. random access in constant time, iteration over all the elements in linear time, add and removal of elements at the end in constant amortized time, etc), but AFAIK there's no other method of fulfilling such requirements other than using a dynamic array.As stated by @Lucretiel, the standard actually requires that the elements are stored contiguously, so it isa dynamic array, stored where the associated allocator puts it.
  1. 实际上,我认为在标准中,它们是根据不同操作的最大复杂度来描述的(例如,恒定时间内的随机访问,线性时间内对所有元素的迭代,在恒定分摊时间最后添加和删除元素,等),但 AFAIK 除了使用动态数组之外,没有其他方法可以满足此类要求。正如@Lucretiel 所述,该标准实际上要求元素连续存储,因此它是一个动态数组,存储在关联分配器放置的位置。

回答by ClosureCowboy

Using the std::vector<T>class:

使用std::vector<T>类:

  • ...is just as fastas 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 beginningor in the middleof 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.

  • ...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).

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

  • ...插入新元素时自动调整大小。

  • ...允许您在向量的开头中间插入新元素,自动“向上”“移动”其余元素(这是否有意义?)。它也允许您删除 中任何位置的元素std::vector,自动将其余元素向下移动。

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

There are twothree main caveats to using std::vector<T>:

使用时有两个三个主要注意事项std::vector<T>

  1. You don't have reliable access to the underlying pointer, which maybe an issue if you are dealing with third-party functions that demand the address of an array.

  2. The std::vector<bool>class is silly. It's implemented as a condensed bitfield, not as an array. Avoid it if you want an array of bools!

  3. During usage, std::vector<T>s are going to be a bit larger than a C++ array with the same number of elements. 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. 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!

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

  2. std::vector<bool>班是愚蠢的。它被实现为一个压缩位域,而不是一个数组。如果您想要一个bools数组,请避免使用它!

  3. 在使用过程中,std::vector<T>s 将比具有相同元素数量的 C++ 数组大一点。这是因为它们需要跟踪少量其他信息,例如它们的当前大小,并且因为每当std::vector<T>s 调整大小时,它们都会保留比所需更多的空间。这是为了防止它们每次插入新元素时都必须调整大小。这种行为可以通过提供 custom 来改变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>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). The std::array<T>class also stores its size (length), which can be very useful.

std::array<T>类是不一样的,为C ++阵列。std::array<T>是 C++ 数组的一个非常薄的包装器,主要目的是向类的用户隐藏指针(在 C++ 中,数组被隐式转换为指针,通常会产生令人沮丧的效果)。所述std::array<T>类还存储它的大小(长度),其可以是非常有用的。

回答by Mark Lakata

To emphasize a point made by @MatteoItalia, the efficiency difference is where the data is stored. Heap memory (required with vector) requires a call to the system to allocate memory and this can be expensive if you are counting cycles. 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. The stack also avoids memory fragmentation. To be sure, std::arraywon't always be on the stack; 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

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

  • small "array" (under 100 elements say) - (a typical stack is about 8MB, so don't allocate more than a few KB on the stack or less if your code is recursive)
  • the size will be fixed
  • the lifetime is in the function scope (or is a member value with the same lifetime as the parent class)
  • you are counting cycles,
  • 小“数组”(比如少于 100 个元素)-(典型的堆栈大约为 8MB,因此如果您的代码是递归的,请不要在堆栈上分配超过几 KB 或更少的空间)
  • 大小将被固定
  • 生命周期在函数范围内(或者是与父类具有相同生命周期的成员值)
  • 你在计算周期,

definitely use a std::arrayover a vector. If any of those requirements is not true, then use a std::vector.

绝对使用std::array超过向量。如果这些要求中的任何一个不正确,则使用std::vector.

回答by psimpson

If you are considering using multidimensional arrays, then there is one additional difference between std::array and std::vector. A multidimensional std::array will have the elements packed in memory in all dimensions, just as a c style array is. A multidimensional std::vector will not be packed in all dimensions.

如果您正在考虑使用多维数组,那么 std::array 和 std::vector 之间还有一个额外的区别。多维 std::array 会将所有维度的元素打包在内存中,就像 ac 样式数组一样。多维 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. They are tightly packed.

指向 c 样式数组 (cConc) 或 std::array (aConc) 中第一个元素的指针可以通过向每个前面的元素加 1 来遍历整个数组。它们被紧紧地包裹着。

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 并让它解决。

回答by Saif al Harthi

A vector is a container class while an array is an allocated memory.

向量是容器类,而数组是分配的内存。