2011-10-08 33 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

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