C ++中逗号运算符与return的不同行为?


83

这(注意逗号运算符):

#include <iostream>
int main() {
    int x;
    x = 2, 3;
    std::cout << x << "\n";
    return 0;
}

输出2

但是,如果return与逗号运算符一起使用,则:

#include <iostream>
int f() { return 2, 3; }
int main() {
    int x;
    x = f();
    std::cout << x << "\n";
    return 0;
}

输出3

为什么逗号运算符的行为与众不同return


Answers:


140

根据运算符优先级逗号运算符的优先级低于operator=,因此x = 2,3;等价于(x = 2),3;。(运算符的优先级决定了运算符如何根据其优先级比其他运算符更严格或更松散地绑定到其参数。)

注意逗号(x = 2),3在这里,不是2,3x = 2首先评估(其副作用已完成),然后丢弃结果,然后3评估(实际上不执行任何操作)。这就是为什么valuex是的原因2。请注意,这3是整个逗号表达式(即x = 2,3)的结果,不会用于分配给x。(将其更改为x = (2,3);x将分配给3。)

对于return 2,3;,逗号表达式为2,32被求值,然后其结果被丢弃,然后3被求值并作为整个逗号表达式的结果返回,该表达式随后由return语句返回


有关表达式语句的其他信息

表达式是运算符及其操作数的序列,用于指定计算。

x = 2,3;表达式语句x = 2,3是这里的表达式。

表达式后跟分号是一个语句。

句法: attr(optional) expression(optional) ; (1)

return 2,3;跳转语句return语句),2,3是这里的表达式。

句法: attr(optional) return expression(optional) ; (1)


1
很好的解释。但是,有一些实际应用吗?还是只是要做错误?
让弗朗索瓦法布尔

7
@Jean-FrançoisFabreIMO这只是令人困惑,根本没有用。
songyuanyao

11
我已经看到它在for循环中使用过一次或两次,而奇怪的是,它可以使代码在数值计算中更清晰
Bathsheba

6
@Jean-FrançoisFabre:就像Bathesheba所说的那样,这样您就可以i += 1, j += 2在for循环中编写类似的内容。有人认为C ++语法(或者更确切地说是C语法,因为这部分是从那里复制的)已经足够复杂,而没有试图定义在编写时逗号的优先级高于赋值,而在编写x = 2, 3时则低x = 2, y = 3
史蒂夫·杰索普

1
@Holger:分号终止一条语句,它不是运算符。这是可以对答案进行调整以使其更加清晰的内容。“ x = 2,3”是带有2个运算符的表达式,由于支持for(;;)的原因,=具有更高的优先级。(正如其他人所说。)但是“返回2、3;” 是包含表达式“ 2,3”的语句。从技术上讲,关键字“ return”没有优先级。(虽然有效,因为它的一部分,接受表达式语句,它被解析最后-低“优先级”,比任何运营商的表达。)
米莎伯杰

32

逗号(也称为表达式分隔)运算符从左到右进行评估。所以return 2,3;等于return 3;

的评估x = 2,3;(x = 2), 3;由于运算符的优先级。评估仍然是从左到右,整个表达式的值为3,其副作用是x假设值为2。


2
您可以在表达式分离运算符上进行编辑和详细说明吗?就像我在@songyuanyao的答案评论中提到的那样,我可以理解为什么return 2,3return (2,3)它们相同。我相信前者应该是(return 2),3
xyz

@BiagioFesta很好地解释了这一部分。
Bathsheba

1
@ prakharsingh95return 2是一个语句(例如由组成的语句for,while,if),而不是表达式。您不能编写egf(return 2)2+return 2。因此,(return 2),3在语法上是无效的。

@chi是的,您是正确的。我的意思是我期望return 2, 3将其解释(return 2), 3
xyz

2
根据C ++语法,@ prakharsingh95return仅在以下情况下会发生:(a)return expression_opt ;和(b)return braced-init-list ;
MM

20

这个说法:

  x = 2,3;

由两个表达式组成:

> x = 2
> 3

由于运算符优先级=比逗号更优先,,所以x = 2评估和 3。然后x将等于2


return代替:

int f(){ return 2,3; }

语言语法为:

return <expression>

注意 return不是表达的一部分。

因此,在这种情况下,两个表达式将被评估为:

> 2
> 3

但是只3返回第二个()。


2
紫外线 非常挑剔,但是如果您标记<expression>为显式可选(从语法的角度来看),那会很好。
Bathsheba

2
的解析树中有5个表达式x=2,3。这两个文字23都在解析树的底部,标识符也在x。这些都是单独有效的表达式。运算符优先级装置,其=发生在解析树,并且组合两个表达式x,并2进入第四表达x=2。最后,第五个表达式由逗号运算符的两个边x=2和组成3。但是,您错误地指出了运算符的优先级决定了评估的顺序。没有。评估顺序由排序规则确定。
MSalters

2
我投票赞成提及返回不是表达的一部分
Daniel Jour

@MSalters我同意你的看法,但我只是不正确地使用这个词“因为不是”“因为”。我的英语不太好!;-=
Biagio Festa

2
“宏观表达”在这里是技术术语吗?当还存在预处理器之类的“宏表达式”时,使用它似乎有些混乱。
senshin

2

尝试应用简单化的方法,仅用括号突出显示优先级:

( x = 2 ), 3;

return ( 2, 3 );

现在我们可以看到二进制运算符“,”从左到右以相同的方式工作。


1
棘手的部分是意识到x = 2, 3本身就是一个表达式,而对于returnreturn <expression>。因此,您将它们阅读为(x = 2, 3)(2, 3)
xyz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.