对未知大小数组的引用的列表初始化:是否应该推断出数组大小?

AnT*_*AnT 5 c++ arrays reference list-initialization

以下代码在Clang中编译良好,并输出int [3]数组的大小

#include <iostream>

int main()
{
  const int (&a)[] = { 1, 2, 3 };
  std::cout << sizeof a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

但是,在GCC中,该声明可以很好地编译,但sizeof a不能编译:显然,GCC拒绝“推导”数组大小,最终a以引用const int []类型的方式结束,这是不完整的。

这种初始化的预期行为是什么?

在这种情况下,9.3.4 / 3似乎是标准的相关部分,但就其本身而言,似乎并不能得出结论。

Bri*_*ian 1

标准在这一点上并不完全明确,我认为 GCC 的解释很可能就是 WG21 的意图,但我不确定。

\n\n

标准的相关部分是 [dcl.array],它描述了如何确定声明符中包含数组形成运算符的声明所声明的类型[]。我引用相关部分:

\n\n
\n

当声明符后跟初始化程序(11.6)或静态数据成员的声明符后跟大括号或等于初始化程序(12.2)时,也可以省略数组边界。在这两种情况下,界限都是根据提供的初始元素(例如 )的数量计算的N(11.6.1),标识符的类型D是 \xe2\x80\x9carray of N T\xe2\x80\x9d。

\n
\n\n

不完全是这仅适用于数组本身的声明,还是也应该适用于对数组的引用,因为在解释 [dcl.ref 时必须递归地查阅 [dcl.array] ](描述&&&运算符)。然而,我认为后一种解释应该被拒绝,因为我们不希望初始化器在[]然而,我认为后一种解释应该被拒绝,因为我们不希望初始化器在声明器中更深地埋藏也就是说,考虑一下这个人为的例子:

\n\n
int (*a[1])(const int (&)[]) = {0};\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里 GCC 和 Clang同意a,并且我认为常识也同意, is的类型int (*[1])(const int (&)[]),而不是 not int (*[1])(const int (&)[1]):拥有初始化器的事实a不会导致内部数组绑定被推导。

\n\n

基于此,我认为 GCC 没有推导代码中绑定的数组是正确的,因此它a具有类型const int (&)[]

\n