【问题标题】:Can a (C/C++) array initialization reference itself? [duplicate](C/C++)数组初始化可以引用自身吗? [复制]
【发布时间】:2014-05-01 08:01:47
【问题描述】:

我想知道以下表单的初始化:

int  array[] = {
v - 1,
array[0] + 1
} ;

在第二个元素的初始化中,使用了第一个元素的值,但是整个数组还没有初始化。这恰好是用 g++ 编译的,但我不确定这是否真的是可移植的和定义良好的构造?

【问题讨论】:

  • @ptomato:因为并非所有编译器都符合标准——尤其是在像这种奇怪的边缘情况下。
  • @ptomato 在 C 和 C++ 中,“试试看”通常是有问题的。许多编译器具有不兼容和非标准的扩展,许多未定义的行为在单个平台上的一些测试中可能看起来是一致的。
  • 我删除了 C 标签,因为您的问题提到您正在使用 g++ 进行编译
  • @DavidHeffernan 但是,如果 C 和 C++ 的行为不同,他可能希望得到答案?
  • @ChristianRau 没有 C/C++ 之类的东西!!

标签: c++


【解决方案1】:

参见 3.3.2 声明点:

名称的声明点紧接在其完整声明符之后(第 8 条)和其之前 初始化器(如果有的话),除非如下所述。 [ 例子:

int x = 12;
{ int x = x; }

这里第二个 x 用它自己的(不确定的)值初始化。 ——结束示例]

所以你正确地引用了数组,它的名字是在=之后知道的。

然后,8.5.1 聚合:

聚合是一个数组或一个类 [...]

17:初始化子句中的完整表达式按照它们出现的顺序进行计算。

但是,我看不到评估值何时实际写入数组的参考,因此我不会依赖它,甚至会声明您的代码定义不明确。

【讨论】:

    【解决方案2】:

    据我所知,这没有明确定义。标准 (C++11, 8.5.1/17) 规定“initializer-clause 中的 full-expressions 按照它们出现的顺序进行计算” ,但我看不到任何需要在评估下一个之前从其 initializer-clause 的结果初始化每个聚合元素的东西。

    【讨论】:

      【解决方案3】:

      (C/C++)数组初始化可以引用自身吗?

      这也是有效的 C 代码。

      C 有一些对应的段落(强调我的)。

      (C99, 6.2.1p7) “结构、联合和枚举标记的范围在声明标记的类型说明符中的标记出现之后开始。每个枚举常量的范围都在出现之后开始它在枚举器列表中定义枚举器。任何其他标识符的范围都在其声明器完成后开始。"

      【讨论】:

        【解决方案4】:

        我认为这是由 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1343 处理的。最初我的报告只是关于命名空间范围对象的非类初始化程序(参见When exactly is an initializer temporary destroyed?),但是如果聚合元素是非类的,那么问题也存在。正如最近的附加说明所解释的那样,即使它是一个类对象,整个聚合初始化似乎也存在,因为这样就不会发生构造函数调用会扩大初始化程序的完整表达式。

        如果您使用的是类而不是 int,并且初始化将是构造函数调用,那么该构造函数调用将是包含聚合初始化器元素的同一个完整表达式的一部分,因此这里的顺序没问题,您的代码将被明确定义。

        【讨论】:

          猜你喜欢
          • 2014-06-17
          • 2010-10-19
          • 1970-01-01
          • 2012-02-11
          • 2017-07-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-17
          相关资源
          最近更新 更多