【问题标题】:Are parentheses around the result significant in a return statement?在 return 语句中,结果周围的括号是否重要?
【发布时间】:2011-06-13 08:33:04
【问题描述】:

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

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

还有这个?

bool returnValue = true;
// Code
return returnValue;

前者在returnValue周围有括号。

【问题讨论】:

  • 感谢 Rob,您成功地抓住了问题的精髓。在本质上,我想知道编译器是否做了什么特别的事情(比如首先尝试评估表达式)或者它是否只是忽略了它。
  • 对于 any c++ / c,这个问题很难回答。最好能更具体地说明语言定义,但 9 年后我不知道如何解决这个问题。
  • 对于C,有一个重复的stackoverflow.com/questions/161879/…

标签: c++ c semantics


【解决方案1】:

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

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

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&语义上的差异与周围的括号直接相关

最新形式的 auto 说明符是在 C++11 中引入的。在C++ Language Spec 中描述为:

指定正在声明的变量的类型将自动 从它的初始化器推导出来。对于函数,指定返回类型是尾随 返回类型 or 将从其返回语句中推导出来(C++14 起)

C++11 还引入了 decltype 说明符,在 C++ Language Spec 中进行了描述:

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

[剪辑]

  1. 如果参数是对象/函数的无括号名称,或者是成员访问表达式(object.member 或指针->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) 相同(上面规则 1 的 int 返回类型),在第二种情况下 return (var1); 它实际上与 decltype((var1)) 相同(@987654338 @ 规则 2b) 的返回类型。

括号使返回类型为int& 而不是int,因此语义发生了变化。 故事的寓意 - “并非所有返回类型上的括号都是平等的”

【讨论】:

  • 不带括号的return语句还是左值表达式吧?除非在这种情况下它被视为 xvalue。不加括号能解释一下return的价值类别吗?
  • return 语句返回对输入它的表达式的读取,即它从它包含的表达式中捕获一个右值并将其返回。我们从不返回左值。某些编译器可能存在与您在此处给出的描述相匹配的错误,并且出于您在此处给出的原因,但绝不应该是 return (x); 等同于 return &x;,也不应该是这样导致返回 x 的值,但类型引用 x。
  • 哇,多么可怕的语言结构。完全……不透明。不过写的不错,谢谢。
  • C++ 是一种非常有趣的语言。但是这些隐藏的“功能”有时会让我发疯……
  • 我们的代码充满了那些不必要的括号。我们也经常使用auto只要我们远离decltype,我们的语义就不会改变吗?我担心当我们转向下一个包含下一个 Visual Studio 的编译器版本时会出现意外行为。
【解决方案2】:

没有区别。

使用括号的一个原因是如果您想在返回之前评估表达式,但在您的示例中,没有理由。见:

Parenthesis surrounding return values

供进一步讨论。

【讨论】:

  • 尽管即使是复杂的表达式,这些括号仍然不会导致不同的行为。它们只是让人类读者更清楚(主观地!)意思。
  • @Karl “使用括号的一个原因是,如果您想在返回之前评估表达式”您能举个例子吗?
  • @ChrisMiddleton 不,因为这里的声明与该线程中的声明一样荒谬。 return m * x + creturn (m * x + c)return ( (m * x) + c ) 等在功能上没有任何区别 - 如果你问我,它看起来也没有更好或更直观。
【解决方案3】:

上例中的括号是多余的;它们实际上被忽略了。

它会像...一样的东西......

int x = (5);

这里的括号也被忽略了。

【讨论】:

  • 嗯,从技术上讲,它们并没有被忽略,它们只是对表达式的值没有影响。
  • @John:有效地被忽略了。 :)
  • +1 ...这是唯一一个表明括号实际上是冗余并表明它们的用法有点愚蠢的答案。
【解决方案4】:

AFAIK,没有什么不同。

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

【讨论】:

  • 大卫,感谢您的链接。我有 Stroustrup 的 C++ 书中的语法,但是(我猜是出于懒惰)没有看那么多,现在我已经在浏览器中添加了书签,我可以更频繁地参考它。
【解决方案5】:

不,您的代码没有区别。

【讨论】:

    【解决方案6】:

    我假设boo 是一个错字,而你在问两者之间是否有区别

    return expr;
    

    return(expr);
    

    答案是否定的。

    【讨论】:

      【解决方案7】:

      没有区别!!

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

      顺便说一句,return 是语句而不是函数。

      【讨论】:

        【解决方案8】:

        不,两者之间没有区别,但如果括号使表达式易于阅读和清晰,则可以包含括号。

        【讨论】:

        • ...但它永远不会。为什么会呢?没有括号的表达式有什么难读的?添加括号对我来说看起来很混乱。至于看起来更清楚,人们是否认为return 是一个贪婪的运算符并且return m * x + c 可能会返回m 并丢弃其余部分,还是什么?
        【解决方案9】:

        你在滥用编译器的速度!

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


        从语义的角度来看?它们完全相同。无论是否有括号,return 语句都会在返回之前对表达式进行完全评估。

        【讨论】:

        • 我的想法完全正确。通过让编译器做不必要的工作来解析无用的杂波,它无缘无故地接近了宇宙的热寂。
        • 你觉得比特币怎么样?
        【解决方案10】:

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

        简单地说,返回表达式周围的括号被那些不太了解类函数宏和函数之间的区别,或者对 C 中的运算符优先级或计算规则的顺序感到困惑的人使用。那里使用括号对编码风格没有好处。

        这样

        return value;
        

        更正确
        return (value)
        

        因为后者表明你不太清楚自己在做什么 :)

        【讨论】:

          【解决方案11】:

          在你的情况下两者都是一样的。

          【讨论】:

          • MM你能解释一下你的评论吗?
          • 如果a5 那么return a++;return (a++);(相同)都将返回5
          • 具体来说,postinc/decrement 返回其操作数的修改前值,再多的括号或其他无效的强制尝试都不会改变这一点。
          猜你喜欢
          • 2021-04-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-05
          • 2016-04-25
          • 2020-05-05
          • 2020-07-09
          • 1970-01-01
          相关资源
          最近更新 更多