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