繁体   English   中英

子数组分配:初始化时应使用“ {…}”初始化聚合对象错误

[英]Subarray assignment: initialization with “{…}” expected for aggregate object error

什么是第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[]可能是“集合对象”。 我只是不明白为什么将语言设置为不起作用。 我知道Line 3为何起作用,但感觉上没有代表性-它是一个数组,所以我宁愿自己将其记录为数组。

可能希望将第1行视为为foo的第0个条目创建引用。 但是,这不是C ++的工作方式。 而是,赋值运算符( = )正在调用复制操作。 因此,C ++将第1行解释为将foo[0]的元素复制到新数组中的指令,该数组不合适地命名为foo_alias_compile_error

这不是什么意思-人们想要参考,而不是副本。 因此,C ++碰巧由于不相关的原因导致了错误并从自己手中救出了一个好消息。

@FrançoisAndrieux提出了可行的解决方案。 这是一个更完整的示例,显示可以使用int (&foo_reference)[10] = foo[0];创建引用(不是副本) 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

数组定义(即C样式数组)中的初始化程序必须为括号列表。

此规则涵盖第1行和第2行,在其中您提供的内容不是括号列表,因此代码不正确。

进一步的信息:当你提供一个支撑列表,然后该列表中的每个元素被取作初始值设定为数组的一个元素。 因此,不可能提供单个初始化程序,该初始化程序会导致设置多个数组元素。

该规则几乎是递归地适用; 如果您有一个数组数组,则初始化程序应为括号列表的括号列表。 但是,有一条规则是在某些情况下可以省略嵌套的花括号(并且代码的行为就像提供了完整的花括号一样)。 例如int x[2][2] = { 1, 2, 3, 4 }; 是允许的,其行为类似于int x[2][2] = { {1, 2}, {3, 4} };

当您不指定数组大小时(在第1行中)。 编译器会为您指定它。 为此,您必须这样做:

/* Line 0 */    int foo[10][10];
/* Line 1 */    int foo_alias_compile_error[] = {foo[0]};

但它仍然有问题。 编译该代码时:

 $ g++ error.cpp
 $ error.cpp:4:28: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
 $    4 |     int fooError[] = {foo[0]};
 $      |                       ~~~~~^
 $      |                            |
 $      |                            int*

因为foo[0]是一个指针,并指向矩阵的第一行(在第1行中)。 你可以这样做:

/* Line 0 */    int foo[10][10];
/* Line 1 */    int foo_alias_compile_error[] = {foo[0][0]};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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