首页 > 解决方案 > 子数组分配:聚合对象错误预期使用“{...}”进行初始化

问题描述

对第 1 行的错误有什么好的解释?

/* Line 0 */    int foo[10][10];
/* Line 1 */    int foo_alias_compile_error[] = foo[0];
/* Line 2 */    int foo_alias_also_errors[10] = foo[0];
/* Line 3 */    int * foo_alias_works = foo[0];

第 2 行的错误并没有真正困扰我,因为我不需要能够重复自己并重新声明数组的大小。但是,第 1 行的错误(使用聚合对象初始化“{...}”)有点让我困惑。我知道这int foo_alias_compile_error[]可能是“聚合对象”。我只是不明白为什么语言设置为不起作用。我理解为什么第 3 行有效,但它有点不具代表性——它是一个数组,所以我宁愿将它作为一个数组进行自我记录。

标签: c++arraysinitialization

解决方案


人们可能希望将第 1 行视为为foo. 然而,这不是 C++ 的工作方式。相反,赋值运算符 ( =) 正在调用复制操作。因此,C++ 将第 1 行解释为将 的元素复制foo[0]到一个名称不恰当的新数组中的指令foo_alias_compile_error

这不是本意——一个人想要一个参考,而不是一个副本。所以,C++ 碰巧因为一个不相关的原因导致了一个错误并从自己那里拯救了一个错误,这很好。

@FrançoisAndrieux 提出了一个可行的解决方案。这是一个更完整的示例,显示可以使用int (&foo_reference)[10] = foo[0];.

int foo[10][10];
for (int i = 0; i < 10; ++i) {
    for (int j = 0; j < 10; ++j) {
        foo[i][j] = i + j * 10;
    }
}
int (&foo_reference)[10] = foo[0];

for (int j = 0; j < 10; ++j) {
    foo_reference[j] = 100 + j;
}

for (int i = 0; i < 10; ++i) {
    printf("foo   [0][%i] is %i\n", i, foo[0][i]);
    printf("foo_refer[%i] is %i\n", i, foo_reference[i]);
}

输出片段

foo   [0][0] is 100
foo_alias[0] is 100
foo   [0][1] is 101
foo_alias[1] is 101
foo   [0][2] is 102
foo_alias[2] is 102
foo   [0][3] is 103
foo_alias[3] is 103

边注

值得一提的是,将数组作为参数的函数会隐式地将它们的数组参数转换为指针(如第 3 行所示)。所以,这就是为什么人们可能错误地认为像 Line 1 这样的东西应该工作的原因之一。

换句话说,下面的代码

void barz(int arg[]) {
    arg[2] = 99999;
}

int another_array[] = {0, 1, 2, 3, 4};
barz(another_array);
printf("another_array[2] is %i\n", another_array[2]);

“正确”打印99999,而不是2.


推荐阅读