2017-08-06 61 views
3

我的電腦關於C++運算符重載

#include <iostream> 

class Int { 
public: 
    Int(int x) : val{x} {} 
    Int operator++() { 
    std::cout << "Int::operator++()\n"; 
    return ++val; 
    } 
    friend Int operator+(Int a, Int b) { 
    std::cout << "operator+(Int, Int)\n"; 
    return a.val + b.val; 
    } 
    friend Int operator*(Int a, Int b) { 
    std::cout << "operator*(Int, Int)\n"; 
    return a.val * b.val; 
    } 

private: 
    int val; 
}; 

int main() 
{ 
    Int a = 1, b = 2; 
    b = ++a + b * b; 
    return 0; 
} 

上運行下面的程序,我得到這個輸出:

operator*(Int, Int) 
Int::operator++() 
operator+(Int, Int) 

據我所知,前綴++比二進制*更高的優先級。但在上面顯示的輸出中,前綴++在之後被稱爲二進制*!是否因爲編譯器將operator +視爲函數調用(導致未指定行爲)?我能否始終將超載運算符視爲函數(當xInt時,會使x = x++的行爲良好定義)?

謝謝!

+2

優先級影響分組,而不是評估順序。是的,'++'具有高於*(用於乘法)的優先級,因此表達式'++ a + b * b'等於'(++ a)+(b * b)'。然而,'+'操作數的評估順序沒有指定,因此不能保證在'++ a'之前或之後評估'b * b'。 – Peter

回答

5

是因爲編譯器將operator+當作函數調用(這會導致未指定的行爲)?

是的。但請注意,如果++ab * b之後進行評估,則無關緊要,因爲最終,這兩項都會正確添加,這遵守運算符優先級規則。

你沒有賦值表達式相當於:

operator+(a.operator++(), operator*(b, b)) 

的函數參數評價的順序是不確定的,所以在技術上,++a可以b * b繞前評估,而且其他的方式。

可我始終認爲重載運算符的功能(這使得x = x++行爲明確定義時xInt)?

是和否。如果Int與「普通」運算符做同樣的事情,那麼否(直到C++ 17),因爲那將是未定義的行爲。但是,如果Int不改變x,例如x++,則是。

+0

「函數參數的評估順序未指定」這不是一個好的前景,b可能是一個函數調用,它會以某種方式進行更改,這可能與使用不同的輸入有很大不同。想象一下當b = ln(a)時的情況。在這種情況下,我們有一個非交換表達式,如果評估順序不同,結果將會不同。 –

+3

@LajosArpad因此,不要寫這樣的代碼 –

+0

@ M.M這是一個直接的結論,但是是一個不必要的限制。 –

1

就我所知,前綴++的優先級高於二進制*

更高的優先級並不意味着前綴增量將在乘法運算符之前被調用,但參數被綁定到相應的操作的順序。