带逗号的相互依赖初始化
Interdependent initialization with commas?
是否完全定义如下:
int x = 42, y = x;
。严格等价于:
int x = 42;
int y = x;
编辑:这个问题不是关于风格的(我知道这是错误的…),这个问题是"理论"
正确答案是
int x = 42, y = x;
和
int x = 42;
int y = x;
通常是等价的(不严格)。
考虑标准§8声明器[dcl.decl]:
3
声明中的每个初始化声明符被单独分析,就像它本身在一个声明中一样。
并在脚注[100]中进一步解释:
带有多个声明符的声明通常等同于相应的声明序列,每个声明符只有一个说明符。这是
T D1, D2,…Dn;
通常等价于
T D1;T D2;…T Dn;
其中T是一个decl-specifier-seq,每个Di是一个init-declarator。
以上保证了
x = 42
和y = x
将分别求值。然而,正如@Praetorian在评论中正确指出的那样,脚注并不规范。这意味着没有很好地定义求值顺序,实现者也可以以相反的顺序实现声明的求值(即。
T Dn; ...T D2; T D1;
)。有人可能认为逗号操作符是保证从左到右求值的。然而,事实并非如此。根据K &R [K &
分隔函数参数、声明中的变量等的逗号不是逗号操作符,也不能保证从左到右求值。
这个问题出现在comp.lang.c++中。很久以前在主题init-declarator-list分析顺序下主持,结论是Yes
。
虽然我看到了完整表达式参数,但是我没有看到求值参数的顺序。所以我认为这是未指定的。
问题的相关部分是:
在下面的声明和定义中:
a = 2, b = a;
是否保证b总是初始化为2 ?如果是,那么我们能说a = 2总是在b = a之前被分析(或求值?)吗?
,答案的相关部分是:
是的。严格地说,程序的可观察行为必须是就好像声明中'a = 2'部分的所有副作用发生在'b = a'部分的求值开始之前。(在当然,在这个简单的例子中,编译器可以赋值2a和b的任意顺序,甚至并行,因为这样做会导致相同的可观察行为)
及以下:
然而,在这个特殊的例子中,分隔了声明器列表放到单独的声明器中;每个声明符都包含一个完整的表达式,声明符依次求值。
更新
是什么使每个初始化声明器成为完整表达式是微妙的,但据我所知,遵循了我在初始化器中使用的相同变量的多个突变列表中使用的相同逻辑c++ 11之前的未定义行为。在本例中,我们从section 8:
中定义的语法开始。init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator initializeropt
下一个重点是初始化器语法,将在8.5
:
小节中介绍。initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
在这两种情况下,我们都有=初始化子句,它将我们带到了赋值表达式,如果我们遵循5节中的语法,将我们带回到primary-expression,它可以给我们一个literal或id-expression。
所以我们确实有用逗号分隔的完整表达式所以我们有:
int x = 42, y = x;
^ ^
| end full-expression
end full-expression
根据1.9
节14我们看到:
与a相关的每个值的计算和副作用全表达式在每次值计算和操作之前进行排序8.
至于评估的顺序,我认为这是没有指定的,适用于缺陷报告430的初始化列表的相同逻辑似乎也适用于这里。在c++ 11中,初始化列表的语言在8.5.4
节中增加了以下内容:
在大括号初始化列表的初始化器列表中初始化子句,包括任何由包展开产生的子句(14.5.3),按它们出现的顺序求值。[…]
没有初始化式的等价物
- 初始化依赖于子类的继承类的常量类成员
- 如何初始化依赖于先前条目的可变参数模板?
- 在不同翻译单元中具有静态存储持续时间的依赖非局部常量浮点变量的常量初始化
- 可以安全地依赖unordered_map中的初始化值(哈希映射)
- 使用依赖于 "this" C++ 的比较结构初始化集合
- 构造函数初始化列表中的循环依赖项
- 初始化依赖于另一个类成员的类成员
- 如何强制依赖静态对象(包括模板成员)的初始化顺序
- C++:使用RAII解析构造函数-初始化器列表依赖项
- 与可以一个从另一个初始化的类的循环依赖关系
- 如何在具有依赖元素类型的模板类构造函数中初始化向量
- 在c++中,当组合对象构造函数有依赖关系时,如何在初始化列表中强制它们的顺序
- 文件间依赖变量的初始化顺序是什么?
- 依赖于初始化的顺序
- 依赖初始化列表
- 在依赖的情况下静态初始化
- 如何初始化模板化类中依赖于T类型的静态const成员
- 为什么标准不允许在模板形参列表中初始化依赖于常量的类型
- 带逗号的相互依赖初始化
- 构造函数执行顺序/顺序:函数中静态变量(类实例)的依赖初始化