在c++中,向量和std::数组

时间:2022-11-24 15:58:32

What are the difference between a std::vector and an std::array in 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++中,std::vector和std:::array的区别是什么?什么时候一个人比另一个人更受欢迎?它们的优缺点分别是什么?我的教科书所做的就是列出它们是如何相同的。

6 个解决方案

#1


247  

std::vector is 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).

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

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. 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. 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. Anyhow, for the very limitation of fixed size it's much less flexible than std::vector.

它比std::vector更有限,但是它通常更有效,特别是对于小尺寸的,因为实际上它主要是围绕c样式数组的轻量级包装器。但是,它是更安全的,因为隐式转换为指针是禁用的,并且提供了大部分的STL-related功能std::向量和其他的容器,所以你可以使用它轻松地与STL算法& co。总之,固定大小的限制,这是更灵活的比std::向量。

For an introduction to std::array, have a look at this article; 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::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 is a dynamic array, stored where the associated allocator puts it.
  2. 实际上,我认为在标准中描述的最大的复杂性不同的操作(例如,在固定时间内随机访问迭代在线性时间内的所有元素,添加和删除元素最后在不断摊销,等等),但是AFAIK没有其他方法实现这样的需求比使用一个动态数组。如@Lucretiel所述,标准实际上要求元素是连续存储的,因此它是一个动态数组,存储在相关分配器所在的位置。

#2


14  

Using the std::vector<T> class:

使用std::向量< 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()方法执行范围检查读取(如果不希望执行此检查,则总是可以使用索引器[])。

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

使用std有两个主要的注意事项::向量 :

  1. 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.

    您无法可靠地访问底层指针,这可能会在处理需要数组地址的第三方函数时出现问题。

  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!

    向量 类是愚蠢的。它是作为压缩位字段实现的,而不是作为数组实现的。如果您想要一个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!

    在使用期间,std::vector s将会比一个元素数目相同的c++数组大一点。这是因为它们需要跟踪少量的其他信息,比如它们的当前大小,并且因为每当std:::vector s大小调整大小时,它们就会保留比所需的更多的空间。这是为了防止每次插入新元素时,它们必须重新调整大小。这种行为可以通过提供自定义分配器来改变,但我从未觉得有必要这么做!


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.

数组 类与c++数组不同。数组 是围绕c++数组的一个非常薄的包装,其主要目的是向类的用户隐藏指针(在c++中,数组被隐式地转换为指针,通常是为了消除效果)。数组 类还存储它的大小(长度),这非常有用。

#3


10  

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::array won'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提出的一点,效率差异在于数据存储的位置。堆内存(向量是必需的)需要调用系统来分配内存,如果您正在计算循环,那么这将是非常昂贵的。堆栈内存(对于数组来说可能)在时间上实际上是“零开销”,因为内存是通过调整堆栈指针来分配的,并且只在函数的输入时执行一次。堆栈还可以避免内存碎片化。可以肯定的是,std::数组并不总是在堆栈上;它取决于您分配它的位置,但是与向量相比,它仍然需要从堆中减少一个内存分配。如果你有一个

  • 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)
  • 小的“数组”(在100个元素下面)—(一个典型的堆栈大约是8MB,所以如果代码是递归的,那么不要在堆栈上分配超过几KB或更少)
  • 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,
  • 你计算周期,

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

一定要使用std::数组除以向量。如果其中任何一个要求不是正确的,那么使用std::vector。

#4


7  

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::数组将会在所有维度中包含内存中的元素,就像c样式数组一样。多维std::向量不会在所有维度中打包。

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:array大。

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::数组到openGL,并将其计算出来。

#5


-12  

One of the advantages that vectors have over arrays is that it is possible to find the current size of a vector using vector_name.size().

矢量对数组的优势之一是,可以使用vector_name.size()找到向量的当前大小。

As you can imagine, this can be quite useful in a variety of situations, where you can fetch number of elements in the array_list easily.

可以想象,这在各种情况下都非常有用,在这些情况下,您可以轻松地在array_list中获取元素的数量。

#6


-13  

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

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

#1


247  

std::vector is 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).

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

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. 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. 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. Anyhow, for the very limitation of fixed size it's much less flexible than std::vector.

它比std::vector更有限,但是它通常更有效,特别是对于小尺寸的,因为实际上它主要是围绕c样式数组的轻量级包装器。但是,它是更安全的,因为隐式转换为指针是禁用的,并且提供了大部分的STL-related功能std::向量和其他的容器,所以你可以使用它轻松地与STL算法& co。总之,固定大小的限制,这是更灵活的比std::向量。

For an introduction to std::array, have a look at this article; 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::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 is a dynamic array, stored where the associated allocator puts it.
  2. 实际上,我认为在标准中描述的最大的复杂性不同的操作(例如,在固定时间内随机访问迭代在线性时间内的所有元素,添加和删除元素最后在不断摊销,等等),但是AFAIK没有其他方法实现这样的需求比使用一个动态数组。如@Lucretiel所述,标准实际上要求元素是连续存储的,因此它是一个动态数组,存储在相关分配器所在的位置。

#2


14  

Using the std::vector<T> class:

使用std::向量< 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()方法执行范围检查读取(如果不希望执行此检查,则总是可以使用索引器[])。

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

使用std有两个主要的注意事项::向量 :

  1. 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.

    您无法可靠地访问底层指针,这可能会在处理需要数组地址的第三方函数时出现问题。

  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!

    向量 类是愚蠢的。它是作为压缩位字段实现的,而不是作为数组实现的。如果您想要一个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!

    在使用期间,std::vector s将会比一个元素数目相同的c++数组大一点。这是因为它们需要跟踪少量的其他信息,比如它们的当前大小,并且因为每当std:::vector s大小调整大小时,它们就会保留比所需的更多的空间。这是为了防止每次插入新元素时,它们必须重新调整大小。这种行为可以通过提供自定义分配器来改变,但我从未觉得有必要这么做!


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.

数组 类与c++数组不同。数组 是围绕c++数组的一个非常薄的包装,其主要目的是向类的用户隐藏指针(在c++中,数组被隐式地转换为指针,通常是为了消除效果)。数组 类还存储它的大小(长度),这非常有用。

#3


10  

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::array won'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提出的一点,效率差异在于数据存储的位置。堆内存(向量是必需的)需要调用系统来分配内存,如果您正在计算循环,那么这将是非常昂贵的。堆栈内存(对于数组来说可能)在时间上实际上是“零开销”,因为内存是通过调整堆栈指针来分配的,并且只在函数的输入时执行一次。堆栈还可以避免内存碎片化。可以肯定的是,std::数组并不总是在堆栈上;它取决于您分配它的位置,但是与向量相比,它仍然需要从堆中减少一个内存分配。如果你有一个

  • 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)
  • 小的“数组”(在100个元素下面)—(一个典型的堆栈大约是8MB,所以如果代码是递归的,那么不要在堆栈上分配超过几KB或更少)
  • 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,
  • 你计算周期,

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

一定要使用std::数组除以向量。如果其中任何一个要求不是正确的,那么使用std::vector。

#4


7  

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::数组将会在所有维度中包含内存中的元素,就像c样式数组一样。多维std::向量不会在所有维度中打包。

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:array大。

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::数组到openGL,并将其计算出来。

#5


-12  

One of the advantages that vectors have over arrays is that it is possible to find the current size of a vector using vector_name.size().

矢量对数组的优势之一是,可以使用vector_name.size()找到向量的当前大小。

As you can imagine, this can be quite useful in a variety of situations, where you can fetch number of elements in the array_list easily.

可以想象,这在各种情况下都非常有用,在这些情况下,您可以轻松地在array_list中获取元素的数量。

#6


-13  

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

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