1

我想在C++中實現一種類似「數字」的數學對象(比如說一個組或一個環中的元素)。我確信我並不是唯一一個處理這個問題的人,所以可能會有大量關於算術運算符重載的「最佳」方式的討論。但是,我找不到滿意的答案(儘管也許我懶得搜索更多)。在現代C++中重載算術運算符的「最佳」方法是什麼?

比方說,我想重載運算符「+」一類A. 的問題是,有太多不同的重載我能想到的:

  1. 運營商+(const的一個& X,常量甲& Y)
  2. 操作者+(常量甲& X,A & & Y)
  3. 操作者+(A & & X,常量甲& Y)
  4. 操作者+(A & & X,A & & Y)
  5. A ::操作者+ =(const的甲& y)的&
  6. A ::操作者+ =(const的甲& y)的& &
  7. 甲::運算+ =(A & & y)的&
  8. A ::操作者+ =(A & & y)的& &

第一個問題。對於A的實例操作所需的所有重載是否儘可能高效,如同「像原始類型一樣」?我認爲對於「普通」情況,右值限定的A :: operator + =不需要(或不應該)被重載。這樣對嗎?我認爲1-4的全部都是必要的。例如,對於案例3,由於x正在移動,我們不需要分配新空間來保存返回值,並且我們可以安全地重新使用爲x保留的分配存儲區。這樣對嗎?

第二個問題。我認爲所有這些重載可能會爲大多數此類情況分享很多代碼。我怎樣才能在不犧牲性能/等的情況下最小化代碼重複?有沒有特殊的技巧/成語來做到這一點? 如果存在,我更喜歡一般的和可擴展的方法。

回答

4

由於選擇「最佳」方式將涉及對操作細節的升值,因此無法給出最一般的答案。

例如最常見的模式(我在下面給出)對矩陣乘法來說不太好,因爲在這種情況下,最簡單的方法是聲明第三個從零開始並讀取兩個參數的矩陣。在這種情況下,您也可能想要使用懶惰評估。

我會建議您確保您的代碼爲所有情況提供了正確答案,並且稍後您的程序可以工作並且您有更多的語言使用經驗時,您可以擔心微優化問題。


對於一類,其中實現+最有效的方法是修改的參數之一,那麼以下兩種情況下涵蓋所有用途,具有較強的異常保證:

A& A::operator+=(A const &y) { /* modify *this using y */ ; return *this; } 
A operator+ (A x, A const& y) { x += y; return x; } 

更多有關上述代碼的作用和原因的說明,請參閱operator overloading megathread

在C++ 03中,使用A const& x代替A x沒有多大區別,但在C++ 11中,這對於第一個參數是右值的情況稍微更優化,因爲資源現在可以從第一個參數中被盜。

關於在operator+=上使用ref-qualifiers的決定。 &&&單獨超載沒有好處。如果你看過使用&的人,理由不是也超載,而是爲在右值上使用+=的嘗試給出編譯錯誤;理由是這可能是一個錯誤。

+0

謝謝,雖然回覆的時間已經很晚了:)看起來上面的方法並不是「最有效」的方式,因爲可能會有不必要的移動,但看起來很合理。當涉及表達式模板時,我能找到一些關於我應該做什麼的參考嗎?我知道一些爲C++ 03編寫的論文,但我不知道C++ 11。再次感謝你。 –