C 中的RVO與NVR優化

2021-08-24 18:22:33 字數 2389 閱讀 8967

rvo技術(return value optimization,匿名返回值優化)

nrvo技術(named return value optimization,具名返回值優化)

關鍵:(1) 語義上,函式呼叫結束,返回值會通過拷貝構造乙個臨時匿名物件傳出來(因為函式體中的都是區域性變數,return後的物件呼叫完成都超過作用域,不存在了)。

(2) 若是直接物件定義,剔除初始化(物件的建立可以分為兩步先定義分配空間,然後初始化),便不會產生那個臨時的物件,省掉一次建構函式和析構函式的呼叫。即對應的語句 x xs = func(),

若return之後的是乙個右值匿名物件,可以看到編譯器可以做進一步的優化,實際並不會構造這麼乙個右值,而是直接給 xs 定義並剔除初始化。

返回值優化,簡稱rvo,是編譯器的一項優化技術,它涉及(功能是)消除為儲存函式返回值而建立的臨時物件。

也即是說rvo的功能是消除函式返回時建立的臨時物件。如下例,

#include using namespace std;

class x

x(const x & x)

}; x func()

int main()

按照《c++ primer 》第四版第214頁所說:「如果返回型別不是引用,在呼叫函式的地方會將函式返回值複製給臨時物件」。也就是說,此時會呼叫乙個建構函式,兩次複製建構函式。分別是:

(1) 建構函式:func()函式中區域性物件的構造

(2) 第一次拷貝建構函式:在函式的呼叫地方,將函式返回值 x 複製給臨時物件temp

(3) 第二次拷貝建構函式:將臨時物件 temp 的值複製給物件 xs

rvo的功能即是需要消除此時的 temp 物件的生成。在《深度探索c++物件模型》第64頁說了編譯器對非引用型別的物件編譯器的處理方式(編譯器優化)。此時編譯器會將返回值函式的原型進行調整,提供乙個介面,即將上述呼叫與函式轉換為如下:

void func(x & result)

int main()

經過這種轉換後,編譯器將只呼叫一次建構函式和一次複製建構函式。操作是:直接將需要賦值的物件作為引用傳入函式中,並在函式返回前,給該物件進行構造。

1)建構函式:func()函式中區域性物件的構造

2)複製建構函式:在 func() 返回前用區域性物件 x 的值來複製構造傳入的 xs 物件(引用物件)

此時可以很明顯看出通過該方法,消除了為儲存返回值而建立的臨時物件,因為此時函式根本沒有返回值(返回型別變為 void)。根據維基百科對 rvo 的定義,此時這種編譯器優化方式就屬於 rvo 了。

在 g++ 上編譯時關閉 rvo ,即,使用指令「g++ -o rvo_test rvo_test.cc -fno-elide-constructors」,此時原始**將呼叫一次建構函式,兩次複製建構函式,符合上述描述。

nrvo是另一種優化技術,也消除了返回值產生的臨時物件,根據維基百科的定義,也屬於 rvo 的一種技術。其具體操作如下例,將上述**優化為:

void func(x & result)      // void func()         //修改了函式原型

// }

int main()

如上的例子中,nrvo的優化比rvo 的優化更進一步,直接將要初始化的物件替代掉返回的區域性物件進行操作。可以看出,進行nrvo 的優化後,此時整個函式將會只呼叫一次建構函式。

(1) 建構函式:構造傳入的引用物件

在 g++ 中,如果不設定關閉 rvo,則g++將會執行rvo,在g++編譯器上執行原始函式,將會僅呼叫一次建構函式。

x func()

int main()

即返回的非引用物件是乙個臨時物件,此時將會同樣進行上述類似nrvo 的優化,只是此時引用物件將不用替換任何區域性變數,直接用構造臨時物件的引數來構造引用物件。即優化為如下形式:

void func(x & result)

int main()

此時的rvo 是 對應 nrvo而言的,即認為 rvo 是nrvo中優化的物件並沒有 named ,是乙個臨時物件。但是按照維基百科的定義,這種優化方式應該只是 rvo 的一種。而不是說這個優化就是 rvo了。網上大家認為的rvo 與 nrvo 事實上應該是沒有什麼關係的,是兩種rvo 的方式,前者的方式是使用臨時物件的構造引數用來構造引用物件;後者的方式是用引用物件替換返回物件進行操作。

總結:(1) rvo 是一項編譯器優化技術,這種技術將消除返回非引用物件在呼叫處建立的臨時物件。

(2) 上述說的第一種編譯器優化方法,nrvo,網上大家說的rvo,這三種技術其實都屬於 rvo技術。

C 中的RVO與NVR優化

語義上,函式呼叫結束,返回值會通過拷貝構造乙個臨時匿名物件傳出來 因為函式體中的都是區域性變數,return後的物件呼叫完成都超過作用域,不存在了 先上 include using namespace std class myclass 預設建構函式 myclass const myclass th...

C 中 NRVO優化與RVO優化

rvo return value optimization 和nrvo named return value optimization 是c 在處理 返回乙個class object的函式 時常用的優化技術,主要作用就是消除臨時物件的構造和析構成本。目前我正在研究 深度探索c 物件模型 對於這兩種常...

C 中的RVO優化和NRVO優化

rvo return value optimization 和nrvo named return value optimization 是c 在處理乙個函式返回類物件並將返回值賦給另乙個物件時,為了減少拷貝構造次數以及析構次數而採用的一種編譯器優化技術。本篇部落格以 深度探索c 物件模型 中例子來總...