【问题标题】:Different behaviour of comma operator in C++ with return?C ++中逗号运算符的不同行为与返回?
【发布时间】: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 的行为不同?

【问题讨论】:

标签: c++ return language-lawyer operator-precedence comma-operator


【解决方案1】:

根据Operator Precedencecomma operator的优先级低于operator=,所以x = 2,3;等价于(x = 2),3;。 (运算符优先级决定了运算符如何绑定到它的参数,根据它们的优先级比其他运算符更紧或更松。)

注意这里的逗号表达式是(x = 2),3,而不是2,3x = 2 首先被评估(并且它的副作用已经完成),然后结果被丢弃,然后3 被评估(它实际上什么都不做)。这就是x 的值是2 的原因。请注意3 是整个逗号表达式的结果(即x = 2,3),它不会用于分配给x。 (改成x = (2,3);x会被赋值为3。)

对于return 2,3;,逗号表达式为2,3,计算2,然后丢弃其结果,然后计算3并作为整个逗号表达式的结果返回,由return statement 稍后。


有关ExpressionsStatements 的其他信息

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

x = 2,3;expression statementx = 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,3return (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)returnexpression_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。非常挑剔,但如果您将&lt;expression&gt; 标记为明确可选(从语法角度来看)会很好。
  • x=2,3的解析树中有5个表达式。文字 23 都位于解析树的底部,标识符 x 也是如此。这些都是单独有效的表达式。运算符优先级意味着=在解析树中出现lower,并将x2这两个表达式组合成第四个表达式x=2。最后,第五个表达式由逗号运算符连接其两侧x=23 形成。但是,您错误地指出运算符优先级决定了评估的 order。它没有。评估顺序由排序规则决定。
  • 我投票赞成提到 return 不是表达式的一部分
  • @MSalters 我同意你的观点,但我只是错误地使用了“因为”这个词,而不是“因为”。我的英语不是那么完美! ;-=
  • 这里的“宏观表达”是一个技术术语吗?当预处理器意义上的“宏表达式”也存在时,使用它似乎有点混乱。
【解决方案4】:

尝试应用简单的方法,只用括号突出优先级:

( x = 2 ), 3;

return ( 2, 3 );

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

【讨论】:

  • 棘手的部分是意识到x = 2, 3 本身就是一个表达式,而对于return 它是return &lt;expression&gt;。所以你把它们读成(x = 2, 3)(2, 3)
猜你喜欢
  • 2018-02-23
  • 2018-03-30
  • 1970-01-01
  • 2017-07-11
  • 2010-12-16
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 2020-07-14
相关资源
最近更新 更多