C ++中逗号运算符的不同行为与返回?
Posted
技术标签:
【中文标题】C ++中逗号运算符的不同行为与返回?【英文标题】:Different behaviour of comma operator in C++ with return? 【发布时间】:2017-01-14 19:29:09 【问题描述】:这个(注意逗号操作符):
#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
的行为不同?
【问题讨论】:
en.wikipedia.org/wiki/Comma_operator 【参考方案1】:根据Operator Precedence,comma operator的优先级低于operator=
,所以x = 2,3;
等价于(x = 2),3;
。 (运算符优先级决定了运算符如何绑定到它的参数,根据它们的优先级比其他运算符更紧或更松。)
注意这里的逗号表达式是(x = 2),3
,而不是2,3
。 x = 2
首先被评估(并且它的副作用已经完成),然后结果被丢弃,然后3
被评估(它实际上什么都不做)。这就是x
的值是2
的原因。请注意3
是整个逗号表达式的结果(即x = 2,3
),它不会用于分配给x
。 (改成x = (2,3);
,x
会被赋值为3
。)
对于return 2,3;
,逗号表达式为2,3
,计算2
,然后丢弃其结果,然后计算3
并作为整个逗号表达式的结果返回,由return statement 稍后。
有关Expressions 和Statements 的其他信息
表达式是一系列运算符及其操作数,用于指定计算。
x = 2,3;
是expression statement,x = 2,3
是这里的表达式。
后跟分号的表达式是语句。
语法:
attr(optional) expression(optional) ; (1)
return 2,3;
是jump statement (return statement),2,3
是这里的表达式。
语法:
attr(optional) return expression(optional) ; (1)
【讨论】:
很好的解释。但是有一些实际的应用吗?还是只是要完成的错误? @Jean-FrançoisFabre IMO 这只是令人困惑,根本没用。 我曾在for
循环中看到过一两次使用它,奇怪的是,它可以使代码在数值计算中更清晰。
@Jean-FrançoisFabre:就像 Bathesheba 所说的那样,您可以在 for 循环中编写类似 i += 1, j += 2
的内容。有人认为 C++ 语法(或者更确切地说是 C 语法,因为这部分是从那里复制的)已经足够复杂,而没有尝试定义逗号的优先级在您编写 x = 2, 3
时高于赋值,但在您编写 @ 时较低987654357@!
@Holger:分号终止语句,它不是运算符。可以对答案进行调整以使其更清楚。 "x = 2 , 3" 是一个有 2 个运算符的表达式,为了支持 for(;;),= 具有更高的优先级。 (正如其他人所说。)但是“return 2, 3;”是包含表达式“2, 3”的语句。 技术上没有优先于关键字“return”的优先级。 (虽然实际上,因为它是接受表达式的语句的一部分,所以它最后被解析——比表达式中的任何运算符in的“优先级”更低。)【参考方案2】:
逗号(也称为表达式分隔)运算符从左到右计算。所以return 2,3;
等价于return 3;
。
x = 2,3;
的评估是(x = 2), 3;
,因为运算符优先级。评估仍然是从左到右,整个表达式的值为3,而x
的副作用假设值为2。
【讨论】:
您能否编辑并详细说明表达式分离运算符?就像我在@songyuanyao 的回答的评论中提到的那样,我可以理解为什么return 2,3
和return (2,3)
是一样的。我认为前者应该是(return 2),3
。
@BiagioFesta 很好地解释了这部分。
@prakharsingh95 return 2
是一个语句(例如由for,while,if
组成的语句),而不是表达式。你不能写例如f(return 2)
或 2+return 2
。所以,(return 2),3
在语法上是无效的。
@chi 是的,你是对的。我的意思是我希望 return 2, 3
被解释为 (return 2), 3
。
@prakharsingh95 根据C++的语法,return
只能出现在以下情况:(a)return
expression_opt;
,和(b) return
braced-init-list ;
.【参考方案3】:
此声明:
x = 2,3;
由两个表达式组成:
> x = 2
> 3
自从operator precedence,
=
的优先级高于逗号,
,因此x = 2
被评估并且在 3
之后。那么x
将等于2
。
改为return
:
int f() return 2,3;
语言语法是:
return <expression>
注意return
不是表达式的一部分。
所以在这种情况下,两个表达式将被评估为:
> 2
> 3
但只会返回第二个 (3
)。
【讨论】:
UV'd。非常挑剔,但如果您将<expression>
标记为明确可选(从语法角度来看)会很好。
x=2,3
的解析树中有5个表达式。文字 2
和 3
都位于解析树的底部,标识符 x
也是如此。这些都是单独有效的表达式。运算符优先级意味着=
在解析树中出现lower,并将x
和2
这两个表达式组合成第四个表达式x=2
。最后,第五个表达式由逗号运算符连接其两侧x=2
和3
形成。但是,您错误地指出运算符优先级决定了评估的 order。它没有。评估顺序由排序规则决定。
我投票赞成提到 return 不是表达式的一部分
@MSalters 我同意你的观点,但我只是错误地使用了“因为”这个词,而不是“因为”。我的英语不是那么完美! ;-=
这里的“宏观表达”是一个技术术语吗?当预处理器意义上的“宏表达式”也存在时,使用它似乎有点混乱。【参考方案4】:
尝试应用简单的方法,只用括号突出优先级:
( x = 2 ), 3;
return ( 2, 3 );
现在我们可以看到二元运算符“,”在两者上的工作方式相同,从左到右。
【讨论】:
棘手的部分是意识到x = 2, 3
本身就是一个表达式,而对于return
它是return <expression>
。所以你把它们读成(x = 2, 3)
和(2, 3)
。以上是关于C ++中逗号运算符的不同行为与返回?的主要内容,如果未能解决你的问题,请参考以下文章