当我找到的所有代码显示重载前缀运算符时返回引用变量时,我感到很困惑。我浏览了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;
}
我认为我只需要更好地理解参考变量。任何人都可以解释为什么前缀运算符应该编码为返回引用变量吗?
答案 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
。