14 More Effective C++—條款20(返回值優化RVO)
阿新 • • 發佈:2018-12-26
針對自定義型別MyClass,我們過載“乘法操作符”。下面將討論為何返回型別為const MyClass, 並解釋什麼是RVO。
class MyClass {
// public function
// private field
}
const MyClass operator * (const MyClass & lhs, const MyClass& rhs);
1,const修飾返回型別
const針對“自增減運算子”。若不加const修飾,則下面語句相當於生成2個臨時物件——obj1+obj2生成的臨時物件;(obj1+obj2)結果加1生成的臨時物件。這麼做會引起對兩個物件的混亂。
(obj1+obj2)++
2,返回型別為const MyClass *
const MyClass * operator * (const MyClass& lhs, const MyClass& rhs);
兩個數做乘法,如果不修改參與運算的物件,就需要生成一個新物件來儲存計算結果。返回一個指標,意味著過載函式內部動態開闢了記憶體空間,為了防止記憶體洩露,過載函式外部需要釋放記憶體空間。
記憶體的申請和釋放不在一個作用域,會導致記憶體洩露問題發生。
3,返回型別為:const MyClass&
const MyClass& operator * (const MyClass& lhs, const MyClass& rhs);
由於函式內部宣告的臨時變數,在離開函式時被銷燬。返回函式內部臨時變數的引用,會引起程式的崩潰。如下面程式碼所示:
int& func() {
int a;
return a;
}
4, 返回值優化(RVO-return value optimization)
如下面“片段1”,若先用命名的臨時變數temp儲存計算結果,然後在返回temp,則函式會再次建立一個匿名的臨時變數,這個匿名臨時變數在賦值給外部變數result。
// 片段1 MyClass result = obj1 * obj2; const MyClass operator * (const MyClass& lhs, const MyClass& rhs) { MyClass temp = // do something return temp; }
當時,當我們返回的是一個建構函式,就可以節省temp到臨時變數,臨時變數到result的開銷。編譯器經過優化,避免了生成臨時變數。如“片段2”所示。這種技術即為“返回值優化技術”
MyClass result = obj1 * obj2;
const MyClass operator * (const MyClass& lhs, const MyClass& rhs)
{
return MyClass(lhs.num() * rhs.num(),
lhs.num0() * rhs.num0());
}
通常,編譯器傾向消除臨時變數,來減少程式執行開銷。