2011-10-08 44 views
1

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

#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

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

其次,存在语义问题。您的代码调用空的构造函数或复制构造函数来创建临时文件,然后破坏临时文件。如果这样的语义含义不合适,那么代码就不会真正起作用,看起来似乎是这样。

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

5

之间的差异:

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

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

是,当使用所述第一码,下面的表达式:

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

增量someNum竭。看到这里的输出:http://ideone.com/y9UlY

然而,当你使用第二个,这

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

增量someNum只有一次!在这里看到的输出:http://ideone.com/eOLdj

这是因为当你从operator++(),第二和第三返回参考++调用称为someNum对同一个对象,因此,它增加了相同的对象,所有的时间。但是,当您按价值归还时,第二个和第三个++会调用您从operator++()返回的临时对象。因此,第二次和第三次调用不会增加someNum,而是增加在表达式结尾处被销毁的临时对象。

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

+0

因此,如果将其与(+)((someNum ++)++)+ ++也只增加someNum一次性后增量进行比较,则第二种更合适!所以如果从这边看,返回一个副本会更好,因为post和pre increment操作符的语义是可比的! – mmmmmmmm

+0

@RüdigerStevens:不是。按照定义,后增加必须返回一个临时值,因为返回的对象和原始对象将具有不同的值。但是在预增加的情况下,返回对象和原始对象将具有相同的值;因此在预增加运算符中创建一个临时变量并返回它是没有意义的。 – Nawaz

+0

描述很好...链接已死。 :) –