More Effective C++ 條款22 (轉)
條款22:考慮用運算子的賦值形式(op=)取代其單獨形式(op):namespace prefix = o ns = "urn:schemas--com::office" />
大多數員認為如果他們能這樣寫程式碼:
x = x + y; x = x - y;
那他們也能這樣寫:
x += y; x -= y;
如果x和y是定義的型別(user-defined type),就不能確保這樣。就C++來說,operator+、operator=和operator+=之間沒有任何關係,因此如果你想讓這三個operator同時存在並具有你所期望的關係,就必須自己實現它們。同理,operator -
, *
, /
, 等等也一樣。
確保operator的賦值形式(assignment version)(例如operator+=)與一個operator的單獨形式(stand-alone)(例如 operator+ )之間存在正常的關係,一種好方法是後者(指operator+ 譯者注)根據前者(指operator+= 譯者注)來實現(參見條款6)。這很容易:
class Rational {
public:
...
Rational& operator+=(const Rational& rhs);
Rational& operator-=(const Rational& rhs);
};
// operator+ 根據operator+=實現;
//有關為什麼返回值是const的解釋,
//參見Effective C++條款21 和 109頁 的有關實現的警告
const Rational operator+(const Rational& lhs,
const Rational& rhs)
{
return Rational(lhs) += rhs;
}
// operator- 根據 operator -= 來實現
const Rational operator-(const Rational& lhs,
const Rational& rhs)
{
return Rational(lhs) -= rhs;
}
在這個例子裡,從零開始實現operator+=和-=,而operator+ 和operator- 則是透過前述的來提供自己的功能。使用這種設計方法,只用維護operator的賦值形式就行了。而且如果假設operator賦值形式在類的public介面裡,這就不用讓operator的單獨形式成為類的友元(參見Effective C++ 條款19)。
如果你不介意把所有的operator的單獨形式放在全域性域裡,那就可以使用模板來替代單獨形式的函式的編寫:
template
const T operator+(const T& lhs, const T& rhs)
{
return T(lhs) += rhs; // 參見下面的討論
}
template
const T operator-(const T& lhs, const T& rhs)
{
return T(lhs) -= rhs; // 參見下面的討論
}
...
使用這些模板,只要為operator賦值形式定義某種型別,一旦需要,其對應的operator單獨形式就會被自動生成。
這樣編寫確實不錯,但是到目前為止,我們還沒有考慮問題,效率畢竟是本章的主題。在這裡值得指出的是三個效率方面的問題。第一、總的來說operator的賦值形式比其單獨形式效率更高,因為單獨形式要返回一個新,從而在臨時物件的構造和釋放上有一些開銷(參見條款19和條款20,還有Effective C++條款23)。operator的賦值形式把結果寫到左邊的引數裡,因此不需要生成臨時物件來容納operator的返回值。
第二、提供operator的賦值形式的同時也要提供其標準形式,允許類的客戶端在便利與效率上做出折衷選擇。也就是說,客戶端可以決定是這樣編寫:
Rational a, b, c, d, result;
...
result = a + b + c + d; // 可能用了3個臨時物件
// 每個operator+ 呼叫使用1個
還是這樣編寫:
result = a; //不用臨時物件
result += b; // 不用臨時物件
result += c; //不用臨時物件
result += d; //不用臨時物件
前者比較容易編寫、de和維護,並且在80%的時間裡它的是可以被接受的(參見條款16)。後者具有更高的效率,估計這對於語言程式設計師來說會更直觀一些。透過提供兩種方案,你可以讓客戶端開發人員用更容易閱讀的單獨形式的operator來開發和debug程式碼,同時保留用效率更高的operator賦值形式替代單獨形式的權力。而且根據operator的賦值形式實現其單獨形式,這樣你能確保當客戶端從一種形式切換到另一種形式時,操作的語義可以保持不變。
最後一點,涉及到operator單獨形式的實現。再看看operator+ 的實現:
template
const T operator+(const T& lhs, const T& rhs)
{ return T(lhs) += rhs; }
T(lhs)
呼叫了T的複製建構函式。它建立一個臨時物件,其值與lhs一樣。這個臨時物件用來與rhs一起呼叫operator+= ,操作的結果被從operator+
.返回。這個程式碼好像不用寫得這麼隱密。這樣寫不是更好麼?
template
const T operator+(const T& lhs, const T& rhs)
{
T result(lhs); // 複製lhs 到 result中
return result += rhs; // rhs與它相加並返回結果
}
這個模板幾乎與前面的程式相同,但是它們之間還是存在重要的差別。第二個模板包含一個命名物件,result。這個命名物件意味著不能在operator+ 裡使用返回值(參見條款20)。第一種實現方法總可以使用返回值最佳化,所以為其生成最佳化程式碼的可能就會更大。
廣告中的事實迫使我指出表示式:
return T(lhs) += rhs;
比大多數編譯器希望進行的返回值最佳化更復雜。上面第一個函式實現也有這樣的臨時物件開銷,就象你為使用命名物件result而耗費的開銷一樣。然而未命名的物件在歷史上比命名物件更容易清除,因此當我們面對在命名物件和臨時物件間進行選擇時,用臨時物件更好一些。它使你耗費的開銷不會比命名的物件還多,特別是使用老編譯器時,它的耗費會更少。
這裡談論的命名物件、未命名物件和編譯最佳化是很有趣的,但是主要的一點是operator的賦值形式(operator+=)比單獨形式(operator+)效率更高。做為一個庫者,應該兩者都提供,做為一個應用程式的開發者,在優先考慮效能時你應該考慮考慮用operator賦值形式代替單獨形式。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990983/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Effective C++ 條款08_不止於此C++
- Effective Modern C++ 系列之 條款2: autoC++
- Effective c++條款11:在operator=中處理“自我賦值”C++賦值
- [讀書筆記][effective C++]條款30-inline的原理筆記C++inline
- 文獻學習——Making Deduction More Effective in SAT Solvers
- 學懂現代C++——《Effective Modern C++》之轉向現代C++C++
- effective C++ : CHAPTER 8C++APT
- 【Effective Modern C++】索引C++索引
- Effective C++筆記C++筆記
- effective C++筆記1C++筆記
- 《Effective C++》讀書筆記C++筆記
- Effective C++ 筆記(3)資源管理C++筆記
- Effective C++ 4.設計與宣告C++
- 條款01: 視C++為一個語言聯邦C++
- 《Effective C++》閱讀總結(三):資源管理C++
- 《Effective C++》第三版-1. 讓自己習慣C++(Accustoming Yourself to C++)C++
- 學懂現代C++——《Effective Modern C++》之型別推導和autoC++型別
- 22. 括號生成-c++C++
- 第22條:理解NSCopying協議協議
- 條款05: 瞭解c++默默編寫並呼叫哪些函式C++函式
- 《Effective C++》第三版-5. 實現(Implementations)C++
- 讀完Java名著《Effective Java》: 我整理了這50條技巧Java
- 《Effective C++》閱讀總結(四): 設計、宣告與實現C++
- 學習進度條2024-05-22
- 【C進階】22、條件編譯分析編譯
- 《Effective C++》第三版-3. 資源管理(Resource Management)C++
- c++切面條題目C++
- 《Effective C++》第三版-4. 設計與宣告(Design and Declarations)C++
- 《Effective Python 第二版》第二條 遵循PEP8風格指南Python
- 《Effective C++》閱讀總結(二):類的構造、析構和賦值C++賦值
- 《看雪服務條款》
- 【C++】C++之型別轉換C++型別
- C++中的條件變數C++變數
- MORE_DETAIL_TECHAI
- TypeScript 之 More on FunctionsTypeScriptFunction
- More web function requests go online concurrently, and web service deployment is faster and more economical!WebFunctionGoAST
- effective java 觀後感Java
- TPCH模型規範、測試說明及22條語句模型
- DNS: More than just namesDNS