Reputation: 883
Why does a two-dimensional array of int initialize contiguously? Meanwhile the two dimensional vector is initialize per set of numbers.
int main()
{
array<array<int, 2>, 2> td{ 2, 6, 4, 8 }; //array of arrays
for (int i = 0; i < 2; ++i)
for(int j = 0; j < 2; ++j)
cout << td[i][j] << ' ';
cout << endl;
vector<vector<int>> vtd{ { 5, 1 }, { 0, 2 } }; //vector of vectors
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
cout << vtd[i][j] << ' ';
return 0;
}
Here are the results:
2 6 4 8
5 1 0 2
Upvotes: 3
Views: 1198
Reputation: 24269
std::vector
is an object encapsulating a set of internal state: { T* data, size_t count, size_t capacity }
. The actual contents of a vector are stored off in memory somewhere else.
By contrast, std::array
is an encapsulation layer around a C-style array. It does not have internal state, but sits directly over a C-array.
std::vector<int> v;
v.reserve(4);
std::array<int, 4> a;
After this, what you have on the stack is as follows:
[ int* v.data ]
[ size_t v.count = 0 ]
[ size_t v.size = 4 ]
[ int[4] ]
As a result, your 2-tier std::vector
is actually a vector of objects,
[ std::vector<int>* v.data --> points to second tier object in heap memory ]
[ size_t v.count ]
[ size_t v.size ]
whereas the std::array
is actually just a cover for int a[2][2]
, which initializes exactly the way you would expect.
Upvotes: 1
Reputation: 15870
std::array
is a very thin wrapper around a static array. It is allocated at compile time, with a known size, and each element is guaranteed to be contiguous, so when you have an array of arrays, they will all be contiguous.
Example:
std::array<T, 4> a;
| a[0] | a[1] | a[2] | a[3] |
std::array<std::array<T, 2>, 2> b;
| a[0][0] | a[0][1] | a[1][0] | a[1][1] |
Since the first array (a[0]
) is guaranteed to be contiguous (as is the second array), and the parent wrapper array is also guaranteed to be contiguous, the entire structure will be contiguous.
For a vector, it is determined at runtime. The dynamic array of a vector is guaranteed to be contiguous, if it is a vector of vectors, each element in the parent vector has a pointer to a separate block of contiguous memory (each "child" vector has a size, capacity, and pointer to a block of contiguous memory).
The analogy follows:
T t[...][...] ====> std::array<std::array<T, ...>, ...>
T** t ====> std::vector<std::vector<T>>
Upvotes: 0
Reputation: 409404
The difference between an array of arrays and a vector of vectors is the same as a normal array of arrays versus a pointer to pointer.
The std::array
class is quite close to normal arrays (which has to be contiguous), while std::vector
is closes to a pointer.
Upvotes: 1
Reputation: 119457
std::array
is an aggregate. When an aggregate is initialized with a braced-init-list like this, each subaggregate, in order, takes as many elements from the list as it requires, and the remainder of the list is used to initialize the next element, and so on. In particular, this means that the first array in td
takes the first two initializers (since it has two elements) and the second array takes the remaining two.
std::vector
is not an aggregate, and has an explicitly defined constructor that takes std::initializer_list
as an argument, which determines the semantics of list-initialization.
Upvotes: 3