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++ – Differences Between std::vector and std::array
arraysc++vector
Related Solutions
A: Almost always [use a vector instead of an array]. Vectors are efficient and flexible. They do require a little more memory than arrays, but this tradeoff is almost always worth the benefits.
That's an over-simplification. It's fairly common to use arrays, and can be attractive when:
the elements are specified at compile time, e.g.
const char project[] = "Super Server";
,const Colours colours[] = { Green, Yellow }
;- with C++11 it will be equally concise to initialise
std::vector
s with values
- with C++11 it will be equally concise to initialise
the number of elements is inherently fixed, e.g.
const char* const bool_to_str[] = { "false", "true" };
,Piece chess_board[8][8];
first-use performance is critical: with arrays of constants the compiler can often write a memory snapshot of the fully pre-initialised objects into the executable image, which is then page-faulted directly into place ready for use, so it's typically much faster that run-time heap allocation (
new[]
) followed by serialised construction of objectscompiler-generated tables of
const
data can always be safely read by multiple threads, whereas data constructed at run-time must complete construction before other code triggered by constructors for non-function-localstatic
variables attempts to use that data: you end up needing some manner of Singleton (possibly threadsafe which will be even slower)In C++03,
vector
s created with an initial size would construct one prototypical element object then copy construct each data member. That meant that even for types where construction was deliberately left as a no-operation, there was still a cost to copy the data elements - replicating their whatever-garbage-was-left-in-memory values. Clearly an array of uninitialised elements is faster.
One of the powerful features of C++ is that often you can write a
class
(orstruct
) that exactly models the memory layout required by a specific protocol, then aim a class-pointer at the memory you need to work with to conveniently interpret or assign values. For better or worse, many such protocols often embed small fixed sized arrays.There's a decades-old hack for putting an array of 1 element (or even 0 if your compiler allows it as an extension) at the end of a struct/class, aiming a pointer to the struct type at some larger data area, and accessing array elements off the end of the struct based on prior knowledge of the memory availability and content (if reading before writing) - see What's the need of array with zero elements?
classes/structures containing arrays can still be POD types
arrays facilitate access in shared memory from multiple processes (by default
vector
's internal pointers to the actual dynamically allocated data won't be in shared memory or meaningful across processes, and it was famously difficult to force C++03vector
s to use shared memory like this even when specifying a custom allocator template parameter).embedding arrays can localise memory access requirement, improving cache hits and therefore performance
That said, if it's not an active pain to use a vector
(in code concision, readability or performance) then you're better off doing so: they've size()
, checked random access via at()
, iterators, resizing (which often becomes necessary as an application "matures") etc.. It's also often easier to change from vector
to some other Standard container should there be a need, and safer/easier to apply Standard algorithms (x.end()
is better than x + sizeof x / sizeof x[0]
any day).
UPDATE: C++11 introduced a std::array<>
, which avoids some of the costs of vector
s - internally using a fixed-sized array to avoid an extra heap allocation/deallocation - while offering some of the benefits and API features: http://en.cppreference.com/w/cpp/container/array.
arrays:
- are a builtin language construct;
- come almost unmodified from C89;
- provide just a contiguous, indexable sequence of elements; no bells and whistles;
- are of fixed size; you can't resize an array in C++ (unless it's an array of POD and it's allocated with
malloc
); - their size must be a compile-time constant unless they are allocated dynamically;
- they take their storage space depending from the scope where you declare them;
- if dynamically allocated, you must explicitly deallocate them;
- if they are dynamically allocated, you just get a pointer, and you can't determine their size; otherwise, you can use
sizeof
(hence the common idiomsizeof(arr)/sizeof(*arr)
, that however fails silently when used inadvertently on a pointer); - automatically decay to a pointers in most situations; in particular, this happens when passing them to a function, which usually requires passing a separate parameter for their size;
- can't be returned from a function; (Unless it is std::array)
- can't be copied/assigned directly;
- dynamical arrays of objects require a default constructor, since all their elements must be constructed first;
std::vector
:
- is a template class;
- is a C++ only construct;
- is implemented as a dynamic array;
- grows and shrinks dynamically;
- automatically manage their memory, which is freed on destruction;
- can be passed to/returned from functions (by value);
- can be copied/assigned (this performs a deep copy of all the stored elements);
- doesn't decay to pointers, but you can explicitly get a pointer to their data (
&vec[0]
is guaranteed to work as expected); - always brings along with the internal dynamic array its size (how many elements are currently stored) and capacity (how many elements can be stored in the currently allocated block);
- the internal dynamic array is not allocated inside the object itself (which just contains a few "bookkeeping" fields), but is allocated dynamically by the allocator specified in the relevant template parameter; the default one gets the memory from the freestore (the so-called heap), independently from how where the actual object is allocated;
- for this reason, they may be less efficient than "regular" arrays for small, short-lived, local arrays;
- when reallocating, the objects are copied (moved, in C++11);
- does not require a default constructor for the objects being stored;
- is better integrated with the rest of the so-called STL (it provides the
begin()
/end()
methods, the usual STLtypedef
s, ...)
Also consider the "modern alternative" to arrays - std::array
; I already described in another answer the difference between std::vector
and std::array
, you may want to have a look at it.
Best Answer
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 ofstd::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 thanstd::vector
.For an introduction to
std::array
, have a look at this article; for a quick introduction tostd::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.