【问题标题】:Is the behavior of return x++; defined?是返回 x++ 的行为;定义?
【发布时间】:2011-01-23 18:15:03
【问题描述】:

例如,如果我有一个具有实例方法和变量的类

class Foo
{

   ...

   int x;
   int bar() { return x++; }
 };

是否定义了返回后递增变量的行为?

【问题讨论】:

    标签: c++ return post-increment


    【解决方案1】:

    是的,相当于:

    int bar()
    {
      int temp = x;
      ++x;
      return temp;
    }
    

    【讨论】:

    • 如果int 不是int,而是MyClassWithOverloadedOperators,那么你就错了。
    • @Pavel:我不同意。具有未实现正确后增量语义的重载后增量运算符的类是错误的。
    • @Void,如果你重载一个后增量,它不会神奇地变成一个 pre-increment,是吗?
    • @Pavel:好的,是的,你在技术上是正确的——一个类可能没有前置增量,或者前置增量可能与后置增量有不同的效果(除了它的pre-ness),但这是一个如此模糊的场景,我认为不值得一提,而且我当然不认为它值得投反对票(假设是你)。
    • @Pavel:我将它从x++ 更改为++x,否则我将根据x++ 定义x++,并且我倾向于避免循环定义。另外,我不认为这是一个错误,就像我没有澄清我的代码仅在没有 #define for temp 或 bar 时才适用...此外,我的示例仅描述int 100% 正确的操作。
    【解决方案2】:

    是的……它会在增加 x 之前返回 x 的值,之后 x 的值将是 + 1……如果重要的话。

    【讨论】:

      【解决方案3】:

      已定义。

      它返回递增前x 的值。如果x 是一个局部(非静态)变量,则此后增量无效,因为一旦函数返回,函数的局部变量就不再存在。但是如果x 是局部静态变量、全局变量或实例变量(如您的情况),则其值将在返回后递增。

      【讨论】:

      • 但是如果自定义类上的++-operator 过载会发生什么?会发挥它的作用吗?
      • @Dario 是的,会的。 "return" 后面的表达式将在 return 执行之前被完全计算。
      • @Dario。是的,和你做return x.dosomething();的原因完全一样,dosomething的效果会在return之前执行。重载后增量不是魔术,它只是一个返回值的函数,它恰好是旧值。
      • @Steve "重载后增量不是魔法,它只是一个返回值的函数,恰好是旧值" - 如果程序员决定这样实现它:-)
      • 是的,公平点。 “碰巧是旧值,如果程序员有他与生俱来的良好意识的话”。
      【解决方案4】:

      是的。

      postincrement (x++) 中,x 的值被评估(在您的情况下返回)添加 1。

      preincrement (++x) 中,x 的值在加 1 之后计算。

      编辑:您可以比较链接中prepost增量的定义。

      【讨论】:

        【解决方案5】:

        大多数编程语言,如 C++,都是按照执行操作的顺序递归的(我在这里没有暗示编译器如何实际实现代码)。由任何定义良好的操作组成的复合操作本身就是定义良好的,因为每个操作都是在后进先出的基础上执行的。

        后增量返回正在递增的变量的值之前递增它,因此return 操作接收该值。无需对此行为进行特殊定义。

        【讨论】:

        • 我认为问题不在于会返回什么值,而在于是否会发生增量。如果你的心智模型认为“返回”会导致函数立即结束,这是一个可以理解的担忧——如果函数已经结束,是否真的有时间应用增量?当然,我们知道答案是,但这只是因为编译器执行了像 Poita 的答案中那样的转换,以确保在应用所有副作用之前函数不会真正返回。
        • 这就是我的意思。在x++“返回”之后遇到return 语句。由于x++ 是一个操作,因此应该将其视为返回,就像Poita_ 提供的演示代码中一样。这样,很容易看出,由于x++ 被执行,其返回值被传递给return 语句。 x++ 会返回并然后递增是没有意义的。
        【解决方案6】:

        我知道这个问题很久以前就已经回答了,但这就是它被定义的原因。 复合运算符基本上是函数的语法糖。 如果你想知道从函数返回后增量是如何发生的,它不会。它发生在运算符“function”返回前一个值之前。

        对于一个整数,想像这样定义的后自增运算符函数:

        int post_increment(int *n)
        {
            int temp = *n;
            *n = *n + 1;
            return temp;
        }
        

        【讨论】:

          【解决方案7】:

          我认为它已定义但不是首选。它给人们带来了困惑。例如,以下代码打印 1 而不是 2。

          #include <iostream>
          #include <cstdlib>
          
          using namespace std;
          
          int foo()
          {
              int i = 1;
              return i++;
          }
          
          int main()
          {
              cout << foo() << endl;
          
              return 0;
          }
          

          【讨论】:

          • 试着改掉using namespace std的习惯。该前缀的存在是有原因的:保护您免受命名冲突,并明确这些函数、数据结构和其他内容的来源。
          猜你喜欢
          • 2011-06-22
          • 1970-01-01
          • 2011-01-24
          • 1970-01-01
          • 2012-10-06
          • 2017-09-23
          • 2019-10-08
          • 1970-01-01
          相关资源
          最近更新 更多