国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C++中用賦值形式op=取代單獨形式op

2019-11-17 05:47:46
字體:
來源:轉載
供稿:網友

  大多數程序員認為假如他們能這樣寫代碼:

  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<class T>
const T operator+(const T& lhs, const T& rhs)
{
 return T(lhs) += rhs; // 參見下面的討論
}

template<class T>
const T operator-(const T& lhs, const T& rhs)
{
 return T(lhs) -= rhs; // 參見下面的討論
}
...
  使用這些模板,只要為operator賦值形式定義某種類型,一旦需要,其對應的operator單獨形式就會被自動生成。

  這樣編寫確實不錯,但是到目前為止,我們還沒有考慮效率問題,效率究竟是本章的主題。在這里值得指出的是三個效率方面的問題。第一、總的來說operator的賦值形式比其單獨形式效率更高,因為單獨形式要返回一個新對象,從而在臨時對象的構造和釋放上有一些開銷。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; //不用臨時對象
  前者比較輕易編寫、debug和維護,并且在80%的時間里它的性能是可以被接受的(參見條款16)。后者具有更高的效率,估計這對于匯編語言程序員來說會更直觀一些。通過提供兩種方案,你可以讓客戶端開發人員用更輕易閱讀的單獨形式的operator來開發和debug代碼,同時保留用效率更高的operator賦值形式替代單獨形式的權力。而且根據operator的賦值形式實現其單獨形式,這樣你能確保當客戶端從一種形式切換到另一種形式時,操作的語義可以保持不變。

  最后一點,涉及到operator單獨形式的實現。再看看operator+ 的實現:

template<class T>
const T operator+(const T& lhs, const T& rhs)
{ return T(lhs) += rhs; }
  表達式T(lhs)調用了T的拷貝構造函數。它建立一個臨時對象,其值與lhs一樣。這個臨時對象用來與rhs一起調用operator+= ,操作的結果被從operator+.返回。這個代碼似乎不用寫得這么隱密。這樣寫不是更好么?

template<class T>
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賦值形式代替單獨形式。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 岐山县| 祁东县| 云阳县| 资源县| 镇远县| 舒城县| 泗水县| 兰州市| 中卫市| 博爱县| 淳安县| 德庆县| 喀喇沁旗| 翼城县| 麟游县| 鸡西市| 乐都县| 罗定市| 富锦市| 临湘市| 邯郸县| 章丘市| 丹凤县| 乡宁县| 林口县| 凉城县| 达拉特旗| 宝清县| 苍梧县| 丰城市| 民权县| 浦江县| 芜湖市| 木里| 错那县| 信阳市| 罗平县| 双城市| 县级市| 榆树市| 林口县|