Postfix运算符重载顺序

时间:2011-06-29 04:07:41

标签: c++ operator-overloading post-increment

  

可能重复:
  Undefined Behavior and Sequence Points

在重载postfix运算符时,我无法理解操作的顺序。让我们来看看下面的两个小例子:

int i = 0;
std::cout << std::endl << "i: " << i;
i = ++i;
std::cout << std::endl << "i: " << i;
i = i++;
std::cout << std::endl << "i: " << i;

MyClass myObject;
std::cout << std::endl << "myObject: " << myObject.getMyValue();
myObject = ++myObject;
std::cout << std::endl << "myObject: " << myObject.getMyValue();
myObject = myObject++;
std::cout << std::endl << "myObject: " << myObject.getMyValue();

出现两种截然不同的行为。输出如下:

i: 0
i: 1
i: 2
myObject: 0
myObject: 1
myObject: 1

你看,不同的行为。这是我的重载操作符方法的概述。

MyClass & MyClass::operator++ ()
{
    ++myValue;
    return *this;
}

MyClass MyClass::operator++ (int postfixFlag)
{
    MyClass myTemp(*this);
    ++myValue;
    return myTemp;
}

好的。前缀很有意义。您可以增加所需的任何内容,然后返回相同的对象,现在已修改,以便分配。但后缀是什么让我沮丧。它应该分配,然后增加。在这里,我们是自我分配。因此,使用内置整数类型,它是有道理的。我将i的值分配给自己,然后i递增。很公平。但是,让我们说MyClass是对int的重新创造。它从0开始,获得前缀递增,然后变为1.然后,关键行。 myObject = myObject++。这跟myObject = myObject.operator++(int postfixFlag)是一回事。它被调用。 myTemp初始化为值1.它增加到2.然后我们返回临时值。如果我们分配给另一个对象,这是有效的。但是在这里我是自我分配的,所以在增加到2之后,myObject被设置为等于用初始值初始化的返回临时对象,我们又回到了1!那讲得通。但这是一种根本不同的行为。

我该如何解决? int怎么做?这个方法一般是怎么写的?您对C ++行为和设计有何评论?等等我现在有点困惑,因为书籍和在线例子似乎总是使用上述方法的变体。

感谢阅读,任何意见都将不胜感激!

1 个答案:

答案 0 :(得分:5)

正如其他人所说,对于int,行为是未定义的。但我想我会试着解释为什么你的MyClass它永远不会达到2。

诀窍是你在后缀版本中采取以下三个步骤:

  1. 制作名为this的{​​{1}}副本(myTemp)。
  2. 增加myValue == 1(所以this->myValue; myTemp.myValue == 1)。
  3. 返回this->myValue == 2myTemp)。
  4. 因此,您要修改myValue == 1,但调用this的代码永远不会再次看到myObject++。它只会查看返回的值,它是 this的副本。

    operator ++的代码很好。问题是你如何使用它 - 你不应该将预增量或后增量的结果写回同一个变量(行为是未定义的)。以下是一些可能更有启发性的代码:

    myObject

    打印:

    int i = 0;
    std::cout << "i: " << i << std::endl;
    int j = ++i;
    std::cout << "i: " << i << ", j: " << j << std::endl;
    int k = i++;
    std::cout << "i: " << i << ", k: " << k << std::endl;
    
    MyClass myObject;
    std::cout << "myObject: " << myObject.getMyValue() << std::endl;
    MyClass myObject1 = ++myObject;
    std::cout << "myObject: " << myObject.getMyValue()
        << ", myObject1: " << myObject1.getMyValue() << std::endl;
    MyClass myObject2 = myObject++;
    std::cout << "myObject: " << myObject.getMyValue()
        << ", myObject2: " << myObject2.getMyValue() << std::endl;
    

    我改变了你的代码,以便不是每次都分配给一个新的变量,而是分配给它自己。请注意,在i: 0 i: 1, j: 1 i: 2, k: 1 myObject: 0 myObject: 1, myObject1: 1 myObject: 2, myObject2: 1 int两种情况下,主变量(MyClass / i)都会递增两次。但是,在预增量的情况下,新变量(myObject / j)采用新值,而在后增量情况下,新变量(myObject1 / { {1}})接受旧值。

    编辑:只是回答问题的另一部分,“Int怎么做?”我假设这个问题意味着“k类中的预增量和后增量代码是什么样的,我怎样才能使我的相同?”答案是,没有“myObject2类”。 int是C ++中的一种特殊内置类型,编译器会特别对其进行处理。这些类型没有用普通的C ++代码定义,它们被硬编码到编译器中。

    注意:对于想要自行尝试的人,以下是问题未包含的int代码:

    int