[19]最後曾提到了在函式通過傳值方式(by value)返回乙個物件時,不可避免地要生成乙個臨時物件,這會嚴重影響到程式的效率,如下例計算兩個分式的乘積:
classcrational
int numer() const
//get numerator
int denom() const
//get denominator
private
:
intnumerator;
intdenominator;
};const crational operator *(const crational& lhs, const crational&rhs)
crational a(
1, 3
);crational b(
2, 3
);crational c = a * b; //
呼叫函式 operator *()
我們來仔細分析一下operator * 完成的功能,生成乙個區域性物件res ,呼叫建構函式進行了初始化,函式返回時,還會生成乙個臨時變數,用res進行copy constructor,返回之後會銷毀res物件,而呼叫c = a * b; 時將臨時物件用來初始化c,然後再銷毀這個臨時變數。
上面這一系列的構造、析構物件,嚴重影響了程式的效能,那麼有什麼辦法可以消除這種影響呢?
能否通過返回乙個物件指標呢?將例項的函式改為:
const crational* operator *(const crational& lhs, const crational&rhs)crational c = * (a * b); //
呼叫函式
暫不說最後呼叫函式的表示式看起來很不自然,最嚴重的問題是這樣寫容易導致記憶體洩漏,因為我們往往會忘記釋放函式返回來的指標。
那能否通過返回物件的reference呢?於是上面的例項的函式被修改為:
const crational& operator *(const crational& lhs, const crational&rhs)crational c = a * b; //
看起來沒啥問題對吧?
貌似這種做法,可以不用生成臨時物件,因為返回的是物件的引用,直接指向res。事實上,這種做法是錯誤的!函式返回的是reference,指向乙個區域性物件,而區域性物件在函式返回時是要被釋放的,因此res在operator *返回時已經不存在了,所以這種做法是不被編譯器允許的!
額...貌似沒什麼其他辦法消除返回的臨時物件了,那麼能否通過其他方式讓編譯器消除生成臨時物件的成本呢?
我們的做法是:返回constructor arguments 取代區域性物件!如下:
const crational operator *(const crational& lhs, const crational&rhs)看起來和最開始的做法沒什麼區別吧....因為還是要生成函式內部臨時物件已經函式返回臨時物件!但是,這種做法下c++允許編譯器將臨時物件進行優化,使它們不存在。如呼叫
crational c = a * b;
臨時物件構造與c的記憶體內,這樣整個過程,你只需付出乙個constructor(用來生成c)的代價,而並沒有函式內部和返回時臨時物件的構造和析構的代價了。
如果將函式再定義為內聯函式,將又會節省函式呼叫的成本。下面是乙個最有效的做法:
inline const crational operator *(const crational& lhs, const crational&rhs)而編譯器這種優化行為,被稱為"returnvalueoptimization"(rvo)!crational c = a *b;
//與下面的語句幾乎具有相同的代價
crational c(a.numer() * b.numer(), a.denom() * b.denom());
效率 條款20 協助完成「返回值優化(RVO)」
函式如果返回物件,對效率狂而言是乙個嚴重的挫折,因為以by value方式返回物件,背後隱藏的constructor和destructor都將無法消除。有的人會返回指標,於是導致下列這種拙劣的語法形式 const rational operator const rational lhs,const ...
協助完成返回值的優化
乙個返回物件的函式很難有較高的效率,因為傳值返回會導致呼叫物件內的構造和析構函式,這種呼叫是不能避免的。問題很簡單 乙個函式要麼為了保證正確的行為而返回物件要麼就不這麼做。如果它返回了物件,就沒有辦法擺脫被返回的物件。就說到這。考慮rational 有理數 類的成員函式operator class ...
C 返回值優化RVO
返回值優化,是一種屬於編譯器的技術,它通過轉換源 和物件的建立來加快源 的執行速度。rvo return value optimization。測試平台 stm32f103vg keil 5.15 背景 我們有個macaddress toarray byte macaddress toarray c...