1. 程式人生 > >14 More Effective C++—條款20(返回值優化RVO)

14 More Effective C++—條款20(返回值優化RVO)

針對自定義型別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());
}

通常,編譯器傾向消除臨時變數,來減少程式執行開銷。