user1508519
user1508519

Reputation:

std::array vs std::vector subtle difference

I wanted to mess around with std::array to see how different it is from std::vector. So far, I've only found one major difference.

Sentence sentence = { "Hello", "from", "GCC", __VERSION__, "!" };  
std::array<std::string, 10> a;
std::copy(sentence.begin(), sentence.end(), a.begin());

int i = 0;
for (const auto& e : a)
{
    i++;
    std::cout << e << std::endl;
}
std::cout << i << std::endl;

// outputs 10

i = 0;
for (const auto& e : sentence)
{
    i++;
    std::cout << e << std::endl;
}
std::cout << i << std::endl;

// outputs 5

for (int i = 0; i < a.size(); i++)
    std::cout << i << " " << a[i] << std::endl;

// outputs 0 Hello
// ...
//         4 !
//         5-9 is blank

for (int i = 0; i < sentence.size(); i++)
    std::cout << i << " " << sentence[i] << std::endl;

// outputs 0 Hello
// ...
//         4 !
// stops here


// The following outputs the same as above
i = 0;

for (auto it = a.begin(); it != a.end(); it++)
{
    std::cout << i << " " << *it << std::endl;
    i++;
}
std::cout << i << std::endl;
i = 0;
for (auto it = sentence.begin(); it != sentence.end(); it++)
{
    std::cout << i << " " << *it << std::endl;   
    i++;
}
std::cout << i << std::endl;

So from what I can see, std::array's size and max_size is redundant, but std::vector's size and capacity can be different or the same. This is even confirmed from this quote:

size and max_size of an array object always match.

So why does std::array have redundant size functions? More importantly, would you consider it a gotcha that std::array's size is not necessarily the same as std::vector's size, because the vector has a capacity? Also, does this mean that std::arrays are safe (i.e., do they have smart pointer management like vectors?)

Upvotes: 3

Views: 1680

Answers (5)

Marshall Clow
Marshall Clow

Reputation: 16670

As you noted, a std::array is always the same size. size() == capacity(). That means when you create a std::array<T, 5>, you get five calls to T's default constructor. A std::vector<T>, on the other hand will not default-construct any elements. Calling reserve(5) on the vector will still not cause any items to be constructed.

Neither std::array nor std::vector have "smart pointer management", at least in the way I think about them. They both provide iterator types, and functions like begin/end/rbegin/rend that let you traverse the elements in the container. When people say "smart pointer", I think about shared_ptr/unique_ptr/auto_ptr/etc.

In general, a std::array is stored on the stack, while a std::vector allocates storage on the heap. In performance critical applications, that is a big advantage for std::array. Allocating memory on the heap can be 100s or 1000s of times slower than using the stack, especially in multithreaded applications.

Upvotes: 1

Andrew Tomazos
Andrew Tomazos

Reputation: 68588

The more important difference is that std::vector has a resize function, whereas std::array does not.

The size of a std::array instance (like that of a normal array) is fixed when it is instantiated (in fact its size must be known at compile-time, and be a constant expression). A std::vector instance however can be resized after it has been instantiated during run-time.

Further std::arrays of different sizes are distinct types, whereas std::vectors of different sizes are the same type.

The only reason to use a std::array over a std::vector, is that a std::array uses less space and is faster. A std::vector needs to store its size and a pointer to a heap-allocated backing store which may have extra padding to allow for resizing. A std::array is allocated in-place (no indirect pointer), and its size function is also known statically so a call to std::array.size() will compile to a constant (it is a constexpr function in fact).

Upvotes: 2

Nomad101
Nomad101

Reputation: 1698

To expand a little, on the subject an std::array follows very closely to the actual design of an array such as char[] in which the max-size of the array is the size of the array. This is because the array can be thought of as having an immutable size. That is a size that can not be changed besides completely reallocating the memory. Unlike a std::vector which can be set to have a capacity and a size that can be anywhere from 0 to that capacity, however once it passes that capacity value each new element will cause a complete recreation and allocation of the underlying array inside of the vector.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409146

To make it compatible with the other containers.

This way you can have a template function which takes any collection and be sure it will work the same no matter if it's a std::vector or an std::array.

Upvotes: 6

Bill
Bill

Reputation: 5764

capacity in vector is the max capacity of a vector..which may or may not be same as its size. size is the current number of elements in vector.

For performance reasons, if you know the max size of the vector in advance (or have a guess), you can pre-determine the vector's capacity (rather than using its default value). This may significantly increase your code's performance as you would not have to reallocate on each iteration (when you add elements).

http://www.cplusplus.com/reference/vector/vector/capacity/

Upvotes: 4

Related Questions