C ++在前缀重载中返回引用变量

时间:2011-10-08 10:14:45

标签: c++ reference overloading prefix

当我找到的所有代码显示重载前缀运算符时返回引用变量时,我感到很困惑。我浏览了parashift.com常见问题解答(http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.14)并不清楚,尽管它说它会很清楚当你读它。我把他们的例子改编成了一个荒谬的,毫无意义的小程序来测试。

#include<iostream>
using namespace std;

class Number {
   public:
      Number& operator++ ();    // prefix ++
      Number  operator++ (int); // postfix ++
      int value() { return value_; }
      void setValue(int value) { value_ = value; }
   private:
      int value_;
};

Number& Number::operator++ () {
   ++value_;
   return *this;
}

Number Number::operator++ (int unused) {
   Number temp;
   temp.setValue(value_);
   ++value_;
   return temp;
}

int main()
{
   Number someNum;
   someNum.setValue(20);
   cout << "someNum : " << someNum.value() << "\n";
   someNum++;
   ++someNum;
   cout << "someNum : " << someNum.value() << "\n";
   return 0;
}

问题是,如果我只是将它声明为Number对象,它就可以了:

#include<iostream>
using namespace std;

class Number {
   public:
      Number operator++ ();    // prefix ++
      Number  operator++ (int); // postfix ++
      int value() { return value_; }
      void setValue(int value) { value_ = value; }
   private:
      int value_;
};

Number Number::operator++ () {
   ++value_;
   return *this;
}

Number Number::operator++ (int unused) {
   Number temp;
   temp.setValue(value_);
   ++value_;
   return temp;
}

int main()
{
   Number someNum;
   someNum.setValue(20);
   cout << "someNum : " << someNum.value() << "\n";
   someNum++;
   ++someNum;
   cout << "someNum : " << someNum.value() << "\n";
   return 0;
}

我认为我只需要更好地理解参考变量。任何人都可以解释为什么前缀运算符应该编码为返回引用变量吗?

2 个答案:

答案 0 :(得分:5)

之间的区别:

Number& Number::operator++ () {
   ++value_;
   return *this;
}

Number Number::operator++ () {
   ++value_;
   return *this;
}

是,当您使用第一个代码时,使用以下表达式:

++(++(++someNum)); 

增加someNum THRICE。请参阅此处的输出:http://ideone.com/y9UlY

但是,当你使用第二个时,这个

++(++(++someNum));

仅增加someNum ONCE !!请参阅此处的输出:http://ideone.com/eOLdj

这是因为当你从operator++()返回引用时,第二个和第三个++会在名为someNum的同一个对象上调用,因此,它会一直递增同一个对象。但是当您按值返回时,第二个和第三个++会在您从operator++()返回的临时对象上调用。因此,第二次和第三次调用不会增加someNum,而是递增在表达式结束时被销毁的临时对象。

现在如果临时对象被破坏,为什么要先创建呢?毕竟,它的预增量运算符,意味着临时对象和原始对象将具有相同的值。因此,良好的设计决策是,在定义预增量运算符时通过引用返回,以避免创建临时,并提高性能。

答案 1 :(得分:2)

首先,存在效率问题。您正在创建该类的新实例,以便无缘无故地返回它。

其次,存在语义问题。您的代码调用空构造函数或复制构造函数来生成临时文件,然后破坏临时文件。如果它具有不恰当的语义含义,那么代码实际上并不起作用,它只是出现。

第三,代码返回错误的东西。考虑一下:++foo.do_something();。使用您的代码,我们在临时对象上调用'do_something'。我们想在预先递增的do_something()上调用foo