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.
6 Answers 6
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).
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
.
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.
(削除) 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.
-
8Regarding your footnote: While true, the standard also guarentees that pointer arithmetic on the internal elements works, which means that it does have to be an array: &vec[9] - &vec[3] == 6 is true.Lucretiel– Lucretiel2012年03月12日 06:17:21 +00:00Commented Mar 12, 2012 at 6:17
-
12I'm pretty sure, that vector doesn't shrink automatically, but since C++11 you can call shrink_to_fit.Dino– Dino2014年09月09日 09:24:40 +00:00Commented Sep 9, 2014 at 9:24
-
2I'm totally confused by the term static array and I'm not sure what the right terminology is. You mean a static size array and not an static variable array (one using static storage). stackoverflow.com/questions/2672085/…. What is the correct terminology? Is static array a sloppy term for an array with a fixed size?Z boson– Z boson2014年10月21日 11:30:05 +00:00Commented Oct 21, 2014 at 11:30
-
6@Zboson: it's definitely not just you, static is quite an abused term; the very
static
keyword in C++ has three different unrelated meanings, and the term is also used often to talk about stuff that is fixed at compile time. I hope that "statically-sized" is a bit more clear.Matteo Italia– Matteo Italia2014年10月21日 12:55:17 +00:00Commented Oct 21, 2014 at 12:55 -
4One thing to note: For real-time programming (where you aren't supposed to have any dynamic allocation/deallocation after startup) std::array would probably be preferred over std::vector.T.E.D.– T.E.D.2017年01月13日 15:20:54 +00:00Commented Jan 13, 2017 at 15:20
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) or as std::span |
Passed by value or as std::span |
Passed by value or as std::span |
Size | sizeof a1 / sizeof *a1 or std::size(a1) |
a1.size() or std::size(a1) |
v1.size() or std::size(v1) |
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 |
-
void foo(T (& arr)[N])
would capture array size. similar magic-arguments-in-function-templatesI.Omar– I.Omar2021年11月14日 18:22:49 +00:00Commented Nov 14, 2021 at 18:22 -
I would add these rows: "| Value semantics | no | yes | yes |" and "| Move | O(N) | O(N) | O(1) |" and "| Swap | O(N) | O(N) | O(1) |"alfC– alfC2022年02月01日 19:11:22 +00:00Commented Feb 1, 2022 at 19:11
-
1What exactly is "Memory efficiency"? The expression can be ambiguous. Also, how the capacity of
std::vector
gets increased on new allocation depends on implementation. E.g. MSVC increases the capacity by x1.5, not x2.starriet 차주녕– starriet 차주녕2022年08月20日 06:44:12 +00:00Commented Aug 20, 2022 at 6:44 -
@starriet주녕차 It sounds clear to me.
std::vector
is less efficient in that the memory it allocates may not fit the size of the data it stores, and less performant because it does multiple memory allocations, which is costly.Константин Ван– Константин Ван2024年02月11日 10:15:59 +00:00Commented Feb 11, 2024 at 10:15 -
Saying
std::vector
is less memory-efficient is strictly wrong: Yes it might over-allocate, but that is a might - but if you try to do that with an array.... yeah you MUST over-allocate. Lets say you make a forum with user-threads. If you implement the content with astd::array
then you MUST specify a max-length and every single comment will then have that length - say 4000 characters. And then most comments are only 100char long and a vector would be significantly better in terms of memory usage (like an order of magnitude better).ABaumstumpf– ABaumstumpf2024年10月16日 12:26:15 +00:00Commented Oct 16, 2024 at 12:26
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
- 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,
definitely use a std::array
over a vector. If any of those requirements is not true, then use a std::vector
.
-
5Nice answer. "To be sure, std::array won't always be on the stack; it depends on where you allocate it" So how could I create a std::array not on the stack with a large number of elements?NoDataDumpNoContribution– NoDataDumpNoContribution2017年01月18日 09:45:55 +00:00Commented Jan 18, 2017 at 9:45
-
8@Trilarion use
new std::array
or make it a member of a class that you use 'new` to allocate.Mark Lakata– Mark Lakata2017年01月18日 15:37:51 +00:00Commented Jan 18, 2017 at 15:37 -
2So this means
new std::array
still expects to know its size at compile time and cannot change its size but still lives on the heap?NoDataDumpNoContribution– NoDataDumpNoContribution2017年01月18日 16:12:29 +00:00Commented Jan 18, 2017 at 16:12 -
1Yes. There isn't a significant advantage to using
new std::array
vsnew std::vector
.Mark Lakata– Mark Lakata2017年01月18日 18:34:18 +00:00Commented Jan 18, 2017 at 18:34 -
Allocation is not all that expensive. In general the OS gives larger chunks and
new
rarely performs any system-calls. And when you are at a point where that becomes an actual issue then you also should have long since used more application-specific data-structures.ABaumstumpf– ABaumstumpf2024年10月16日 12:29:11 +00:00Commented Oct 16, 2024 at 12:29
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.
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.
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.
This means that a std::vector<std::vector<int>>
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.
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.
-
nested vectors, nested std::array and 2D arrays are VERY DIFFERENT in what functions they provide. with vectors you are still dealing with dynamic size - so while your 3x5 array always has those exact same 15 elements the vectors can all grow independently. And with
std::span
you can access the elements just the same as an multi-dimensionalarray
and if you want you can do that with a simple 1D vector so you have basically the same memory layout. Withstd::vector
you can also provide your own allocator to use the stack.ABaumstumpf– ABaumstumpf2024年10月16日 12:41:11 +00:00Commented Oct 16, 2024 at 12:41
Using the std::vector<T>
class:
...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).
There are (削除) two (削除ここまで) three main caveats to using 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 ofbool
s!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 wheneverstd::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 customallocator
, but I never felt the need to do that!
Edit: After reading Zud's reply to the question, I felt I should add this:
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.
-
9It's 'just as fast" as using a dynamically-allocated built-in array. On the other hand, using an automatic array might have considerably different performance (and not only during allocation, because of locality effects).Ben Voigt– Ben Voigt2013年08月27日 18:13:36 +00:00Commented Aug 27, 2013 at 18:13
-
8For non-bool vectors in C++11 and later, you can call
data()
on astd::vector<T>
to get the underlying pointer. You can also just take the address of element 0 (guaranteed to work with C++11, will probably work with earlier versions).Matt– Matt2015年06月25日 18:01:02 +00:00Commented Jun 25, 2015 at 18:01 -
2In last paragraph you mean C array ? Right ?frakod– frakod2021年06月18日 08:53:54 +00:00Commented Jun 18, 2021 at 8:53
A vector is a container class while an array is an allocated memory.
-
28Your answer seems to address
std::vector<T>
versusT[]
, but the question is aboutstd::vector<T>
versusstd::array<T>
.Keith Pinson– Keith Pinson2013年01月23日 16:36:06 +00:00Commented Jan 23, 2013 at 16:36
std::vector
vs.std::array
and how the terms are different.std::array
is not the same as a C++ array.std::array
is a very thin wrapper around C++ arrays, with the primary purpose of hiding the pointer from the user of the class. I will update my answer.