C++ 是否使用逗号进行初始化?
以下定义是否完美:C++ 是否使用逗号进行初始化?,c++,c++11,initialization,language-lawyer,undefined-behavior,C++,C++11,Initialization,Language Lawyer,Undefined Behavior,以下定义是否完美: int x = 42, y = x; i、 e.严格等同于: int x = 42; int y = x; 编辑:问题不是关于风格(我知道这是错误的…),问题是“理论性的”正确答案是 int x = 42, y = x; 及 通常是等效的(不严格)。 考虑到标准第8条声明人[dcl.decl]: 3声明中的每个init声明符都会单独进行分析,就像它自己在声明中一样 在脚注[100]中进一步说明: 具有多个声明器的声明通常相当于具有单个声明器的相应声明序列 声明人。就是
int x = 42, y = x;
i、 e.严格等同于:
int x = 42;
int y = x;
编辑:问题不是关于风格(我知道这是错误的…),问题是“理论性的”正确答案是
int x = 42, y = x;
及
通常是等效的(不严格)。
考虑到标准第8条声明人[dcl.decl]:
3
声明中的每个init声明符都会单独进行分析,就像它自己在声明中一样
在脚注[100]中进一步说明:
具有多个声明器的声明通常相当于具有单个声明器的相应声明序列
声明人。就是
D1,D2。。。Dn
通常相当于
T D1;T D2。。。T-Dn
其中T是一个decl规范序列,每个Di是一个初始声明器
- 上述保证将分别评估
和x=42
。然而,正如评论中正确指出的那样,脚注不是规范性的y=x
- 这意味着评估顺序没有很好地定义,实现者也可以按相反的顺序(即,
)执行声明的评估tdn;…td2;td1;
- 有人可能会说逗号运算符保证从左到右求值。然而,情况并非如此。根据K&R[K&R II,3.6 p.63],这也适用于C++:
是
虽然我看到了完整表达式参数,但我没有看到求值顺序参数。所以我认为这是未指明的
问题的相关部分是:
在本声明和定义中:
INTA=2,b=a
是否保证b总是初始化为2?如果是,那么
我们能说a=2总是在b=a之前进行分析(或评估)吗
答案的相关部分是:
对。严格地说,程序的可观察行为必须是
就好像声明中“a=2”部分的所有副作用一样
在开始评估“b=a”零件之前发生。(在
当然,在这个简单的示例中,编译器可以指定2
以任何顺序,甚至并行的方式向a和b发送,因为这样做
将导致相同的可观察行为。)
再往下看:
然而,在这个特殊的例子中,它确实分离了声明器
列为单独的声明者;每个声明器包含一个完整的
表达式,并按顺序计算声明符
更新
使每个init declator成为完整表达式的原因很微妙,但据我所知,遵循的逻辑与我在中使用的相同。在本例中,我们从第8节中定义的语法开始:
下一个重点是初始化器语法,该语法将在第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
在这两种情况下,我们都有=initializer子句,它将我们带到赋值表达式,如果我们遵循第5节中的语法,它将带我们回到主表达式,它可以给我们一个文本表达式或id表达式
因此,我们确实有完整的表达式,由语法逗号分隔,因此我们有:
int x = 42, y = x;
^ ^
| end full-expression
end full-expression
根据第1.9节第14段,我们看到:
每个值的计算和副作用与
完整表达式在每次值计算和边计算之前排序
与要计算的下一个完整表达式关联的效果。8
至于评估的顺序,我认为这没有规定,同样的逻辑适用于初始值设定项列表似乎也适用于这里。在C++11中,初始值设定项列表的语言是固定的,在8.5.4节中添加了以下内容:
在带括号的init列表的初始值设定项列表中
初始值设定项子句,包括由包扩展产生的任何
(14.5.3),按照其出现的顺序进行评估。[……]
初始值设定项没有此类等效项。请参阅:@Deduplicator Why not?不是每个声明符都排序了吗?相关的吗@LightnessRacesinOrbit:鉴于许多人认为OP问题hss undefined behavior中的代码是一种需要单独声明的代码样式标准,真的很愚蠢吗?@Damon:我计划与其他程序员合作。脚注是非规范性的。“我认为脚注中的注释通常为实现留出了足够的回旋余地,以便按照相反的顺序对其进行评估,并且仍然是符合要求的。”Praetorian我同意脚注的非规范性,但标准中的引用明确指出它们是分开分析的。是的,这非常清楚。但是计算D1,D2。。。Dn代码>作为tdn。。。t2;T D1
也在分别分析它们。逗号运算符为。但这不是逗号运算符,这里只是init声明符的分隔符-§8/1声明中出现的init声明符列表是一个逗号分隔的声明符序列,“通常是等效的,而不是严格的”-那么你是说有可能y
不会被初始化为42
?我更喜欢它,因为它涉及到了标准所说的细节。但是,我不知道你是如何反驳我最初的批评的:初始值设定项是一个表达式,而不是初始化。初始值设定项是一个声明符,不是一个表达式,因为它没有出现在第5节中,但它可以包含和表达式,每个表达式都将是一个完整表达式,因为它不是子表达式。是的,这就是我的全部观点:)标准在哪里保证
initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
int x = 42, y = x;
^ ^
| end full-expression
end full-expression