3

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?)

  • 1
    The last sentences makes me think that you may have some confusion about what a `std::array` actually is; maybe have a look [here](http://stackoverflow.com/questions/4424579/stdvector-versus-stdarray-in-c/4424658#4424658) for a quick comparison. – Matteo Italia May 05 '13 at 02:28
  • You might think that resizability or lack thereof, and dynamic vs static allocation were bigger differences... Also, needing the size as a template argument (which enables static allocation) – Ben Voigt May 05 '13 at 02:42
  • 6
    The difference between `std::array` and `std::vector` is FAR from subtle – Charles Salvia May 05 '13 at 03:32

5 Answers5

6

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.

awesoon
  • 32,469
  • 11
  • 74
  • 99
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

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/

Bill
  • 5,263
  • 6
  • 35
  • 50
2

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).

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
1

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.

Nomad101
  • 1,688
  • 11
  • 16
1

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.

Marshall Clow
  • 15,972
  • 2
  • 29
  • 45