第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为何起作用,但感觉上没有代表性-它是一个数组,因此我宁愿将其自我记录为数组。
答案 0 :(得分:0)
人们可能希望将第1行视为为foo
的第0个条目创建引用。但是,这不是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
。
答案 1 :(得分:0)
数组定义(C样式数组,即必须)中的初始化程序必须是支撑列表。
此规则涵盖第1行和第2行,您在其中提供的内容不是括号列表,因此代码不正确。
更多信息:当您提供括号列表时,列表的每个元素都将用作数组的 an 元素的初始化程序。因此,不可能提供单个初始化程序,该初始化程序会导致设置多个数组元素。
此规则几乎适用于递归;如果您有一个数组数组,则初始化程序应为括号列表的括号列表。但是,有一条规则是在某些情况下可以省略嵌套的花括号(并且代码的行为就像提供了完整的花括号一样)。例如,允许int x[2][2] = { 1, 2, 3, 4 };
,其行为类似于int x[2][2] = { {1, 2}, {3, 4} };
。
答案 2 :(得分:-1)
当您不指定数组大小时(在第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]};