在c++中,std::vector和std::array之间有什么区别?什么时候应该优先选择一个?它们各自的优点和缺点是什么?我的课本只列出了它们的相同之处。
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).
由于它将元素存储在堆上分配的内存中,因此相对于静态数组,它有一些开销。
array是一个模板类,它封装了一个静态大小的数组,存储在对象本身中,这意味着,如果在堆栈上实例化类,数组本身将在堆栈上。它的大小必须在编译时已知(它作为模板参数传递),并且它不能增长或缩小。
它比std::vector更有局限性,但它通常更有效,特别是对于较小的大小,因为在实践中它主要是c风格数组的轻量级包装器。然而,它更安全,因为指针的隐式转换被禁用,并且它提供了std::vector和其他容器的许多与STL相关的功能,所以你可以很容易地与STL算法等一起使用它。无论如何,由于固定大小的限制,它比std::vector灵活得多。
关于std::array的介绍,请看这篇文章;要快速介绍std::vector及其上可能的操作,您可能需要查看它的文档。
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.
使用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. ...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<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. It's implemented as a condensed bitfield, not as an array. Avoid it if you want an array of bools! 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!
编辑:在阅读了Zud对这个问题的回复后,我觉得我应该加上这个:
std::array<T>类与c++数组不同。std::array<T>是c++数组的一个非常薄的包装器,主要目的是对类的用户隐藏指针(在c++中,数组被隐式转换为指针,通常会产生令人沮丧的效果)。std::array<T>类还存储它的大小(长度),这非常有用。
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
小的“数组”(少于100个元素)-(一个典型的堆栈大约是8MB,所以不要在堆栈上分配超过几KB的空间,如果你的代码是递归的) 尺寸是固定的 生命期在函数作用域中(或者是与父类具有相同生命期的成员值) 你在计算周期,
一定要使用std::array而不是vector。如果这些要求中的任何一个不符合,那么使用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并让它工作。
将上述讨论总结为表格,以供快速参考:
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 |