How can I initialize 2d array with a list of 1d ar

2020-04-04 15:19发布

问题:

How can I initialize 2d array with a list of 1d arrays?

void main()
{
    int a[] = { 1,2,3 };
    int b[] = { 4,5,6 };
    int array[][3] = { a,b };
}

回答1:

raw arrays in C++ are kind of second class citizens. They can't be assigned and they can't be copied, which means you can't use them to initialize other arrays, and their name decays into a pointer in most circumstances.

Lucky C++11 offers a solution. std::array acts like a raw array, but it doesn't have the drawbacks. You can use those instead to build a 2d array like

std::array<int, 3> foo = {1,2,3};
std::array<int, 3> bar = {3,4,5};
std::array<std::array<int, 3>, 2> baz = {foo, bar};

and if you have C++17 support you can leverage class template argument deduction to get rid of having to specify the template parameters and the code simplifies to

std::array foo = {1,2,3};
std::array bar = {3,4,5};
std::array baz = {foo, bar};

which you can see working in this live example



回答2:

Use std::array.

auto a = std::array{ 1,2,3 };
auto b = std::array{ 4,5,6 };
auto array = std::array{ a,b };

Demo



回答3:

The way you presented - not at all... You can have:

int array[][3] = { { 1, 2, 3 }, { 4, 5, 6 } };

If you still need a and b, you could then have these as pointers:

int* a = array[0];
int* b = array[1];

or a bit closer to your original try: References to array:

int(&a)[3] = array[0];
int(&b)[3] = array[1];

This way, you could still e. g. apply sizeof to a and b...

Or the other way round: create an array of pointers

int a[] = { 1,2,3 };
int b[] = { 4,5,6 };
int* array[] = { a, b };

All these solutions presented so far have in common that both a and array[0] access exactly the same data. If you actually want to have two independent copies instead, then there's no way around copying the data from one into the other, e. g. via std::copy.

If you switch from raw array to std::array, though, you can have this kind of initialisation (with copies) directly:

std::array<int, 3> a;
std::array<int, 3> b;
std::array<std::array<int, 3> 2> array = { a, b };


回答4:

std::array is the way to go here, but if you want to stick to the means of the language (and not the standard lib), and your combined array has the same life time as its constituents, and if the data can be shared, you can have an array of pointers to arrays and say

int a[] { 1,2,3 };
int b[] { 4,5,6 };

decltype(a) *abArr[] {&a, &b};
// equivalent to 
// int (*abArr[])[3] { &a, &b };

Note that this is not a 2-dimensional array, and its elements are not integers. But you can still range-loop through both dimensions because the pointers are true pointers to a fixed-size array (as opposed to pointers to a mere int as a result of array decay, which couldn't be range-looped).

Since the array elements are pointers it is necessary to dereference row:

for (auto const& row : abArr)
    for (auto const& e : *row)
        cout << e << " ";

Live example: http://coliru.stacked-crooked.com/a/cff8ed0e69ffb436