One of the common questions when starting to study the container abstractions in C++20 is “Should I use std::array or std::vector?”. The correct answer is “use what is best suited for the current situation”. That is not good enough, obviously. In this short article, I will try to answer this question based on the intrinsic nature of these two containers.
std::array is a convenient wrapper over C-style native array. It is therefore no less efficient than using the native array. I would recommend this nice article if you wish to learn more about this container.
This also means that when you create an object of std::array as a local variable inside a function, for example, the whole space is reserved on that function’s stack, just like the C-style array. In other words, the storage for the elements is not allocated separately on the heap, and it cannot grow or shrink! Here is a short code fragment to illustrate the point:
When you run the program, this is the output:
The above example clearly tells us that the space occupied by an std::array object is the same as a native array and is reserved statically. This also gives us a warning signal: when we use std::array as a local variable, we have to be careful about its size (i.e, number of elements in the array). Depending on the memory constraints on the machine/device where our code will run, we have to ensure that there is sufficient stack space for creating the local object. It is difficult to recommend a specific threshold, but if you need space for a large array, the stack is probably not the right area for it.
Now, what about std::vector? Unlike std::array, std::vector does not allocate all the required memory statically (it cannot know a priori). Although the implementation might reserve some memory initially, it is meant to grow dynamically. Hence the memory for the elements it contains is allocated on the heap (of course, the vector object will contain some data for book keeping purposes and this will be of fixed size).
Take a look at the following code:
Note that the variable “vector1” is created empty and no items are added later. The other vectors have different number of items. Let us see what happens when we run this program:
You can see that irrespective of the number of items the vector contains, the size of the vector object is a constant value of 32 bytes (implementation dependent). This size corresponds to the state variables (pointer, etc.) that are part of the object and does not reflect the items added to the vector.
The above two examples give us clues as to the usage pattern of these two containers. When we do not know, a priori, the number of items our container will hold, std::vector is the one to consider. When the number of items is known ahead of time and is not a large number, std::array can be considered.
What to do if we know the number of items ahead of time, but the number is large? We can still use std::array, but create it on heap instead, perhaps using std::unique_ptr. The following code shows how:
std::array and std::vector are among the most commonly used containers, so it is important to become comfortable with their proper usage.
The example source is available here.
Have a nice week!
Recent Comments