简体   繁体   中英

List initialization for array<array<int, M>, N>

When initializing a 2D array we can do

int data[2][2] = {{1, 2}, {3, 4}}; // OK

we can also use

int data[2][2] = {1, 2, 3, 4}; // OK

which makes sense since a 2D array still is a continues chunk of memory.

When using the array class instead of the base type, this works

array<array<int, 2>, 2> data = {1, 2, 3, 4}; // OK

Which again makes sense, since array class doesn't have any extra data and ends up as a continues chunk of memory as well.

But the 2D list does not work:

array<array<int, 2>, 2> data = {{1, 2}, {3, 4}}; // Error

I can also initialize this

vector<array<int, 2>> data = {{1, 2}, {3, 4}}; // OK

But couldn't find anyway to initialize:

array<vector<int>, 2> = ????

My question is:

Is there a fundamental design reason for this (My guess is something related to stuff happening at compile-time vs run-time)? Or is this just an implementation decision for the compiler I am using (GCC)?

std::array doesn't have any user-defined constructor (like std::vector ), it just contains a underlying array, when performing aggregate initialization you need one more braces for it.

array<array<int, 2>, 2> data = {{{{1, 2}}, {{3, 4}}}};
//                             ^                    ^  <- for array<array<int, 2>, 2>
//                              ^                  ^   <- for the underlying array
//                               ^      ^              <- for the 1st array<int, 2>
//                                ^    ^               <- for its underlying array
//                                         ^      ^    <- for the 2nd array<int, 2>
//                                          ^    ^     <- for its underlying array

We can omit braces as

array<int, 2> data = {1, 2};
array<array<int, 2>, 2> data = {1, 2, 3, 4};

because of brace elision :

The braces around the nested initializer lists may be elided (omitted), in which case as many initializer clauses as necessary are used to initialize every member or element of the corresponding subaggregate, and the subsequent initializer clauses are used to initialize the following members of the object.

That means the above code code be written as

array<array<int, 2>, 2> data = {{{1, 2}, {3, 4}}};

And array<array<int, 2>, 2> data = {{1, 2}, {3, 4}}; fails because it's interpreted as:

array<array<int, 2>, 2> data = {{1, 2}, {3, 4}};
//                             ^              ^  <- for array<array<int, 2>, 2>
//                              ^    ^           <- for the underlying array
//                                      ^    ^   <- excess elements; std::array has only one underlying array

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM