如何使用1d数组列表初始化2d数组?

7

如何使用1d数组列表初始化2d数组?

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

4
请注意,在C++中,即使您从不从main函数返回任何值,它的返回类型也必须为int - François Andrieux
@FrançoisAndrieux:我的Visual Studio没有抱怨。我正在使用C++17。 - Second Person Shooter
2
Visual Studio 不会抱怨很多事情。所有编译器和 IDE 都是如此。首先,因为语言不要求编译器诊断每一种错误,其次,许多平台提供默认启用的扩展,这些扩展在最好的情况下不可移植,在最坏的情况下不符合标准。事实上,语言定义的 main 的形式都要求在 C++ 中返回类型为 int。关于 main 的一个值得注意的事情是,任何平台都可以定义任何形式的 main,包括返回 void 的形式,尽管它们根据定义不可移植。 - François Andrieux
4个回答

14

C++中的原始数组有些像二等公民。它们不能被赋值和复制,这意味着您不能使用它们来初始化其他数组,并且它们的名称在大多数情况下会衰减为指针。

幸运的是,C++11提供了一种解决方案。std::array就像原始数组一样,但没有这些缺点。您可以使用它们来构建2D数组,例如:

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};

如果您的C++17支持,您可以利用类模板参数推导来消除必须指定模板参数的问题,代码简化为:

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

您可以在这个 实时示例 中看到它的工作。


这种情况下它是有效的,但要注意这种初始化可能会发生的不直观的事情(有时必须发生)。如果你没有 foobar,你就必须写成 std::array<std::array<int, 3>, 2> array = { 0, 1, 2, 3, 4, 5 };,而不是 ... = { { 0, 1, 2 }, { 3, 4, 5 } };(后者无法编译)! - Max Langhof
2
@MaxLanghof 您也可以使用 std::array test = {std::array{1,2,3},std::array{3,4,5}} - NathanOliver
1
不幸的是,CTAD目前无法通过使用指令来缩短名称 :( - NathanOliver

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

Demo


5
你的表达方式不太好,可以有以下几种改进方案:
int array[][3] = { { 1, 2, 3 }, { 4, 5, 6 } };

如果你仍需要a和b,那么你可以将它们作为指针:
int* a = array[0];
int* b = array[1];

或者更接近您原来的尝试:数组引用:
int(&a)[3] = array[0];
int(&b)[3] = array[1];

这样,您仍然可以对ab应用sizeof等操作...

或者反过来:创建指针数组。

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

到目前为止,所有这些解决方案都有一个共同点,即a和array[0]都访问完全相同的数据。如果你实际上想要两个独立的副本,那么就必须将数据从一个复制到另一个,例如通过std :: copy

如果你从原始数组切换到std :: array,则可以直接进行此类初始化(带有副本):

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

3

std::array 是最好的选择,但如果您想坚持使用语言本身的手段(而不是标准库),并且您的组合数组与其构成部分具有相同的生命周期,并且数据可以共享,则可以创建指向数组的指针数组,如下所示:

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

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

请注意,这不是一个二维数组,其元素也不是整数。 但你仍然可以在两个维度上进行范围循环,因为指针是真正的指向固定大小数组的指针(而不是指向简单 int 的由于数组衰减而产生的指针,这些指针不能进行范围循环)。
由于数组元素是指针,因此需要取消引用“row”:
for (auto const& row : abArr)
    for (auto const& e : *row)
        cout << e << " ";

演示实例:http://coliru.stacked-crooked.com/a/cff8ed0e69ffb436

这是一个关于 IT 技术的实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接