2016-07-25 80 views
2

這是爲什麼執行:C++ - 爲什麼要op + =而不是其他方式實現op +?

T& T::operator+=(const T&) { 
    // ... implementation ... 
    return *this; 
} 

T operator+(const T& lhs, const T& rhs) { 
    T temp(lhs); 
    return temp += rhs; 
} 

傳播更多的時候比這一個:

T& T::operator+=(const T& rhs) { 
    *this = *this + rhs; 
    return *this; 
} 

T operator+(const T& lhs, const T& rhs) { 
    // ... implementation ... 
    return some_result; 
} 

沒有任何理由可言,還是僅僅是我見過的人實現它隨機的巧合這種方式多次在我閱讀的文獻中,而且從來沒有其他方式?

+0

測試第二個,你會發現它不起作用。究竟它是如何工作的將取決於'// ...實現...'中發生了什麼,但它不會起作用。最有可能的是,'return * this + rhs;'完全不會對'this'做任何事情。 – user2357112

+0

@ user2357112:我的回答是解釋你發現的問題,還是另一個? –

+1

請不要通過查看答案來更改帖子。它會使答案無效 – P0W

回答

9

operator+必須創建一個新對象來保存結果。 operator+=不需要新的對象。

如果您按照operator+編寫operator+=,那麼您最終將支付額外的新對象創建,分配(或交換)和銷燬,所有這些都不需要。除此之外,在許多處理器上,硬件直接支持+=和類似的操作,其中結果存儲回輸入寄存器之一,而不存儲到第三寄存器(如+)。

順便說一句,你的(原來的,現在編輯的)代碼隱藏了部分額外工作中的錯誤。實際上,你需要:

T& T::operator+=(const T& rhs) 
{ 
    *this = *this + rhs; // creation of temporary, move assignment, and destruction of temporary 
    return *this; 
} 

更糟的是,你的(再次原來,現在編輯)建議實施的operator+未能正確地返回新的對象,它返回一個懸掛引用來代替。這是未定義的行爲。


對於那些有興趣,第一operator+實現可以進一步通過使用改進的傳遞按值:

T operator+(T lhs, const T& rhs) 
{ 
    lhs += rhs; 
    return lhs; 
} 

現在,如果的operator+左手操作數是一個暫時的,移動的構造將被使用,避免副本。儘管使用NRVO,但在任何結果代碼中都沒有太多優勢。

+0

但是,我們不要創建一個新的對象嗎?我們在一個案例中創建T temp,並在另一個案例中創建some_result。它是不是歸結爲同一件事? –

+1

@EnnMichael:在運算符+ =的直接實現中沒有任何東西可以創建一個新對象。考慮'std :: complex ',它看起來就像'T&std :: complex :: operator + =(const std :: complex &rhs){re + = rhs.re; im + = rhs.im;返回*這個; }'沒有創建新的臨時對象,每條語句都完全映射到單個CPU指令(在通用體系結構上)。 –

+1

@EnnMichael:如果您詢問'operator +'(而不是'+ =')的變體是否創建臨時對象,是的,這是必要的。這也是我的答案開始說的。您建議的方法存在的問題效率極低,「+ =」。 –

相關問題