结果括号是否在return语句中有意义?


79

函数内部的这两个语句之间有区别吗?

bool returnValue = true;
// Code that does something
return(returnValue);

还有这个?

bool returnValue = true;
// Code
return returnValue;

前者周围有括号returnValue


感谢Rob,您成功地抓住了问题的精神。在Essence中,我想知道编译器是否做了什么特别的事情(例如尝试首先求值表达式)还是只是忽略了它。
Jose Villalta

1
任何 c++/都很难回答这个问题c。最好在语言定义上更具体,但我不知道9年后如何解决。
乔纳斯·斯坦

Answers:


120

从C ++ 14开始,它们经常是。

C ++ 14增加了一种边缘情况,其中返回值周围的括号可能会改变语义。此代码段显示了要声明的两个函数。唯一的区别是在返回值两边加上括号。

int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))

在第一个中func1返回int,在第二个中func1返回int&语义上的差异与周围的括号直接相关

autoC ++ 11中引入了最新形式的说明符。在C ++语言规范中,它描述为:

指定要从其初始值设定项自动推断出要声明的变量的类型。对于函数,指定返回类型为尾随返回类型,或从其返回语句中推论得出(自C ++ 14起)

同样,C ++ 11引入了decltypeC ++语言规范中描述的说明符:

检查实体的声明类型或查询表达式的返回类型。

[片段]

  1. 如果参数是对象/函数的未括号名称,或者是成员访问表达式(object.member或pointer-> member),则decltype指定此表达式指定的实体的声明类型。

  2. 如果参数是类型T的任何其他表达式,则

    a)如果表达式的值类别是xvalue,则decltype指定T &&

    b)如果表达式的值类别为左值,则decltype指定T&

    c)否则,decltype指定T

[片段]

请注意,如果将对象的名称加上括号,则该对象将成为左值表达式,因此decltype(arg)和decltype((arg))通常是不同的类型。

在C ++ 14中,decltype(auto)允许函数返回类型使用。原始示例就是括号之间的语义差异发挥作用的地方。回顾原始示例:

int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))

decltype(auto)允许从return语句上的实体/表达式推导函数中的尾随返回类型。在第一个版本中,return var1;它实际上与返回类型相同decltype(var1)int上述规则1的返回类型),而在第二种情况下,return (var1);它实际上与返回类型(规则2bdecltype((var1))int &返回类型)相同。

括号使返回类型int&代替int,从而改变了语义。故事的寓意-“并非所有返回类型的括号都相等”


没有括号的return语句仍然是左值表达式,对吗?除非在这种情况下将其视为xvalue。您能否解释不带括号的收益的价值类别?
void.pointer '16

1
return语句返回读入的表达式的读值,即,它从包含的表达式中捕获右值并返回该右值。我们从不返回左值。某些编译器可能会存在与您在此处给出的描述相匹配的错误,并且由于您在此处给出的原因,但决不能return (x);等于return &x;,也不应该导致返回。 x的值,但类型引用为x。
西奥多·默多克

4
哇,这是多么丑陋的语言。只是完全不透明。不错的文章,谢谢。
保罗·桑德斯

5
C ++是一种非常有趣的语言。但是这些隐藏的“功能”有时
会让

我们的代码充满了那些不必要的括号。我们也auto经常使用。只要我们远离,语义就不会改变decltype吗?当我们转到包含下一个Visual Studio的下一个编译器版本时,我担心会发生意外的行为。
OneWorld '18

6

没有区别。

使用括号的原因之一是,如果您想在返回之前对表达式求值,但是在您的示例中,没有理由。看到:

括号内的返回值

有待进一步讨论。


3
尽管使用复杂的表达式,但这些括号仍不会引起不同的行为。它们只是使含义对人类读者更加(主观地!)。
aschepler 2011年

@Karl“使用括号的一个原因是,如果您想在返回之前对表达式求值”,您能举个例子吗?
克里斯·米德尔顿

3
@ChrisMiddleton不,因为此处的声明与该线程中的声明一样荒谬。return m * x + creturn (m * x + c)return ( (m * x) + c )等等之间没有功能上的区别。-如果您问我,它看起来也不会更好或更直观。
underscore_d

5

上面例子的括号是多余的;他们实际上被忽略了。

就像...

int x = (5);

这里的括号也被忽略。


嗯,从技术上讲,它们不会被忽略,它们只是对表达式的值没有影响。
约翰·博德

1
@John:实际上被忽略了。:)
詹姆斯

3
+1…这是唯一说明括号实际上是多余的并表明其用法有点愚蠢的答案。
Konrad Rudolph

4

AFAIK,没什么不同。

在C ++中,表达式可以采用以下形式:expr(expr)。因此,后者是具有更多类型的表达式。有关此内容的更多信息,请参阅语法(查找“表达式”)。


大卫,感谢您的链接。我在Stroustrup的C ++书中有语法,但是(出于惰性,我想)不必那么多看,因为现在我将其标记在浏览器中,因此可以更经常地引用它。
Jose Villalta


3

我认为boo是拼写错误,您问的是两者之间是否有区别

return expr;

return(expr);

答案是不。


2

没有不同!!

如果涉及复杂的表达式,人们会使用括号。

BTWreturn是不是函数的语句。


2

不会,两者之间没有区别,尽管如果可以使表达式易于阅读和清除,则可以加上括号。


1
...但是从来没有。为什么会这样?不带括号的表达式很难读?对我来说,加上括号似乎很混乱。从表面上看,人们是否认为这return是一个贪婪的运算符,并且return m * x + c可能会返回m并丢弃其余的运算符?
underscore_d 2016年

1

您正在滥用编译器的速度!

括号的存在不仅减慢了预处理阶段,而且还生成了更复杂的抽象语法树:更多的内存,更多的计算。


从语义上看?它们是完全相同的。不管是否有括号,该return语句都会在返回表达式之前对表达式进行完全求值。


5
我的想法正好。通过使编译器进行不必要的工作来解析无用的杂物,无缘无故地逼近了宇宙的热死。
Maxim Egorushkin 2011年

4
您对比特币有何看法?
杰里米·尼古拉

1

它们是相同的。我经常看到括号语法,并且我总是问使用它的人:为什么?没有人能回答他们为什么使用它。

直截了当地总结一下,那些不太了解函数式宏和函数之间差异的人,或者对C中的运算符优先级或评估规则顺序感到困惑的人使用了返回表达式的括号。样式受益于括号。

从而

return value;

比以下更正确

return (value)

因为后者表明您不太了解自己在做什么:)


-3

两者在您的情况下是相同的。


MM您能解释一下您的评论吗?
Zeshan Khan 2015年

1
如果a是,5return a++;return (a++);(相同)都将返回5
MM

2
具体来说,后递增/递减返回其操作数的修改前值,并且括号的数量或其他无效的尝试都不会改变该值。
underscore_d
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.