rvo (return value optimization) 和nrvo (named return value optimization) 是c++在處理乙個函式返回類物件並將返回值賦給另乙個物件時,為了減少拷貝構造次數以及析構次數而採用的一種編譯器優化技術。
本篇部落格以《深度探索c++物件模型》中例子來總結這兩種優化技術。**片段如下:
class point3d
cout << "operator="
}}point3d factory()
int main()
這個例子中的point3d類中顯式定義了建構函式、拷貝建構函式、析構函式以及過載了賦值運算子,並在內部加入了一些列印資訊來檢視這些函式的呼叫情況。
1)不做任何返回值優化。在g++中有乙個選項-fno-elide-constructors可以去掉任何返回值優化。最終列印情況如下:
constructor //factory函式中構造po物件
copy
constructor //factory函式中用po物件拷貝構造臨時物件_temp
deconstructor //factory函式中返回時,析構掉區域性物件po
copy
constructor //main函式中用factory函式中拷貝構造的臨時物件拷貝構造物件p
deconstructor //析構臨時物件_temp
deconstructor //main函式結束時,析構物件p
可以看出,不做任何優化的話就是有兩次拷貝構造和析構,對照注釋很容易理解
2)做rvo優化,vs在debug模式下使用rvo而不用nrvo。對應的輸出如下:
constructor
copy
constructor
deconstructor
deconstructor //main函式中p的析構
在《在深度探索c++物件模型》書中,對應的解釋為,編譯器將factor函式改寫為了如下的偽**形式:
factory(const point3d &_result)
而main函式中賦值語句改寫為:
point3d p;
factory(p);
這樣將p直接做為引數,在factory()函式中進行構造,就不需要先將po拷貝構造出臨時物件_temp,再析構_temp。
3)那能不能直接構造p,而不需要先構造po,再拷貝構造p呢。答案是可以的,需要將factory()函式改寫為如下形式:
factor()
這種返回臨時物件的寫法,如果開啟了編譯器的rvo優化,factory()函式的大致偽**實現就會改寫為:
factory(const point3d &_result)
相應的列印情況,就為:
constructor //p的構造
deconstructor //p的析構
這樣將拷貝建構函式和析構函式又減少了一次。
4)有時程式設計師會不注意將factory()函式改寫為(3)中的形式,那能不能不改寫也能起到(3)中的優化效果呢,這時nrvo優化就上場了。
如果程式設計師還是將factory()函式寫成:
point3d factory()
有了nrvo優化編譯器還是會將其優化成(3)中的形式,對應輸出結果當然同樣只有一次構造和析構。
我在vs下和gcc下分別在debug模式和release模式下驗證發現,gcc在debug和release模式下都支援nrvo優化,在vs的debug模式下只支援rvo優化,release模式下支援nrvo優化。對於其它的編譯器,還暫時沒做相應的驗證。
C 中的RVO優化和NRVO優化
rvo return value optimization 和nrvo named return value optimization 是c 在處理乙個函式返回類物件並將返回值賦給另乙個物件時,為了減少拷貝構造次數以及析構次數而採用的一種編譯器優化技術。本篇部落格以 深度探索c 物件模型 中例子來總...
C 中 NRVO優化與RVO優化
rvo return value optimization 和nrvo named return value optimization 是c 在處理 返回乙個class object的函式 時常用的優化技術,主要作用就是消除臨時物件的構造和析構成本。目前我正在研究 深度探索c 物件模型 對於這兩種常...
編譯器優化RVO和NRVO
編譯器選擇 如果想自己實踐rvo和nrvo,不要在vs下嘗試 這裡的vs不是指vs code 用支援g 的編譯器去測試 我這裡用的是mingw 因為vs無論在debug還是release下都是無法關閉rvo優化的,dubug下可以關閉nrvo優化。而g 預設都是執行nrv0優化的。rvo nrvo ...