【问题标题】:List-initialization of a reference to an array of unknown size: is it supposed to deduce the array size?对未知大小数组的引用的列表初始化:是否应该推断出数组大小?
【发布时间】:2019-04-05 22:26:32
【问题描述】:

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

#include <iostream>

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

然而,在 GCC 中,声明编译得很好,但 sizeof a 没有:显然 GCC 拒绝“推断”数组大小并最终以 a 作为对 const int [] 类型的引用,这是不完整的。

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

9.3.4/3 似乎是此类情况下标准的相关部分,但它本身似乎并不能最终回答这个问题。

【问题讨论】:

  • const int (&amp;a)[] = ... 是否有效?标准规定了可以省略边界的情况 (eel.is/c++draft/dcl.array#3),但这仅适用于数组本身,不适用于对数组的引用。
  • @Daniel Langr:链接中的文字说:“除了允许不完整对象类型的声明,还可以省略数组绑定......” .这实际上恰好是一个允许不完整类型的声明:在 C++ 中对不完整类型的引用是可以的。从一开始,C++ 中就存在未知边界的数组作为不完整类型。尽管在这种情况下它是否应该保持不完整,但我并不清楚。因此问题。
  • @AnT:它说:。所以它不允许引用类型(不过我不确定这是有意的)。
  • @geza:嗯...不。您引用的措辞是指上述“附加”案例,即在我上面引用的部分之后描述的那些。它与上述“允许不完整对象类型的声明”没有任何关系或关联,也不以任何方式禁止它们。那里的措辞非常清楚。
  • @AnT:我可能误解了你,或者标准。这是完整的句子:。这里不就是这样吗?界限是根据初始化程序计算的。 “允许的不完整类型”不是指“extern Foo a[];”这样的情况吗? (这里的 Foo 可能不完整)?在您的情况下,声明的类型必须是完整的,因为它是一个定义(据我了解,对不完整类型的引用是完整的类型)。

标签: c++ arrays reference list-initialization


【解决方案1】:

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

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

当声明符后跟 initializer (11.6) 或静态数据成员的声明符后跟 brace-or-equal- 时,也可以省略数组绑定初始化器 (12.2)。在这两种情况下,边界都是根据提供的初始元素(例如,N)的数量(11.6.1)计算的,D 的标识符类型是“NT 的数组”。

这并不完全适用于数组本身的声明,或者它是否也应该适用于对数组的引用,因为在解释 [dcl.ref 时必须递归查询 [dcl.array] ](描述&amp;&amp;&amp; 运算符)。但是,我认为后一种解释应该被拒绝,因为当[] 被更深地埋在声明符中时,我们不会期望初始化程序导致推断出一个界限。也就是说,考虑一个人为的例子:

int (*a[1])(const int (&)[]) = {0};

这里 GCC 和 Clang agree,我认为常识也同意,a 的类型是 int (*[1])(const int (&amp;)[]),而不是 int (*[1])(const int (&amp;)[1])a 拥有初始化程序的事实不会导致内部数组必然会被推导出来。

基于此,我认为 GCC 在不推断代码中绑定的数组方面是正确的,因此 a 的类型为 const int (&amp;)[]

【讨论】:

  • 能否请您阅读问题下的cmets?不是吗,const int (&amp;a)[] = ... 格式不正确?因为他们说:,所以不允许引用数组。
  • @geza:你似乎在自相矛盾。在您最近的 cmets 中,您似乎建议 9.2.3.4 仅适用于 array 声明。但这不是 array 声明。它是一个 reference 声明。为什么你一直引用那个显然不适用于const int (&amp;a)[] 声明的措辞(不管人们如何解释 9.2.3.4 的范围)?
  • @geza 恐怕我根本听不懂你在说什么。
  • @AnT:如果我们完全忽略 9.2.3.4(因为这是一个引用声明),那么是什么指定 a 引用的对象的大小为 3?
  • @geza:引用初始化的规则(在我的问题中链接)说,为了初始化该引用,我们必须生成一个 referenced 类型的prvalue。此纯右值的类型中不再包含引用。问题基本上归结为在这种情况下,它的类型是否已经“冻结”为不完整的数组类型const int[],或者它仍然保留从初始化程序获取特定大小const int[3] 的能力。从字面上看,措辞似乎暗示该类型应该是“冻结的”(即 GCC 是正确的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-11
  • 2014-10-27
  • 1970-01-01
相关资源
最近更新 更多