函式返回值與RVO優化

2021-08-19 10:48:12 字數 2215 閱讀 4294

rvo優化:

return value optimistic,指當乙個函式返回乙個值型別而非引用型別時,可以繞過拷貝/移動建構函式,直接在呼叫函式的地方構造返回值。要發生rvo需要有三個條件:

1,如果型別是自定義型別,那麼此時的拷貝/移動建構函式是可訪問的

2,返回型別必須與實際型別完全一致,即返回時不需要進行隱式型別轉換,否則不能進行rvo,因為不知道使用者定義的類會不會有特別的型別轉換建構函式

3,返回型別必須為值型別,而非引用型別,當然,這也是為什麼需要rvo的原因--避免拷貝帶來的額外開銷

下面的**是乙個rvo的演示

class

foo

foo(

const foo& f)

foo(

int i)

foo(foo &&f)

~foo()

};foo fun(

int i = 9

) int

main()

輸出結果是這樣的:

default

constructor

destructor

在執行foo bob = fun()時, 本意是主動呼叫拷貝建構函式,但是由於foo定義了移動建構函式,使用普通的函式匹配規則來確定使用哪個建構函式,由於fun()的返回值是右值,所以使用移動建構函式,由於此時移動建構函式是可訪問的,編譯器可以繞過拷貝/移動建構函式,直接構造物件。所以不會先由fun()返回乙個臨時物件,再利用這個臨時物件構造bob的過程,而是這個構造的臨時量就是bob,不拷貝。

另外,函式的執行過程是,先執行函式體,在遇見return時,將return的值拷貝/移動到呼叫函式的地方,然後開始析構棧中的物件,但是rvo允許直接在呼叫函式的地方構造應該return的那個物件,所以這一次移動建構函式也被繞過了。

如果我們把這些優化都關掉,會得到這樣的結果:

default

constructor

move constructor

destructor

move constructor

destructor

destructor

即先構造f1,然後遇見return,移動到臨時物件,析構f1,將臨時物件移動到bob,析構臨時物件,臨時bob

但是如果我們這麼寫fun(),編譯器就不會進行rvo:

foo fun(int i = 9

)

return

f2;}

前面說到,rvo是在構造需要return的物件時,直接在上一級棧幀中構造它(即呼叫函式的地方),而不是在它自己的棧幀中構造,這樣就避免了將該物件拷貝至上級棧幀中的過程,可是修改後的fun,編譯器無法在編譯器推斷出哪個物件會被返回,也就無從進行rvo,因此我們得到了這樣的結果

default

constructor

default

constructor

move constructor

destructor

destructor

destructor

先構造出兩個物件f1,f2,移動f2到函式呼叫處,析構f1,f2,這裡只有乙個移動建構函式是因為編譯器優化掉了bob的移動建構函式。

總結:1, 在構造物件時,如果有移動建構函式,使用普通函式匹配規則構造物件,否則正常構造。

2,正常建構函式時,使用'='就是主動呼叫移動建構函式即string s = "999"是讓編譯器先把"999"轉換為string型別,再拷貝/移動,哪怕string型別有乙個string(const char *)的建構函式,也要這麼幹

3,上面兩個過程,在移動/拷貝建構函式都可以訪問時,如果為移動建構函式,則直接拿著右值來使,不再呼叫移動建構函式,如果是拷貝建構函式,則直接拿著轉換後的臨時string來用,不拷貝,也就讓string s = "999" 變成了string s("999") (很明顯,隱式轉換用的就是string(const char *)這個建構函式)

4, rvo優化只有同時滿足:返回值是值型別,並且無需型別轉換,編譯器能夠在編譯器判斷出哪個變數會被返回時,才會發生。發生rvo時,如果某個物件instance1會被返回,則不在該函式的棧幀中構造它,而是在呼叫函式的地方也就是上級棧幀中構造instance1。

5,函式在執行到return語句時,理論上先講返回值拷貝/移動置呼叫的地方,然後開始析構函式棧中的自動物件

C 返回值優化RVO

返回值優化,是一種屬於編譯器的技術,它通過轉換源 和物件的建立來加快源 的執行速度。rvo return value optimization。測試平台 stm32f103vg keil 5.15 背景 我們有個macaddress toarray byte macaddress toarray c...

C 返回值優化RVO

返回值優化,是一種屬於編譯器的技術,它通過轉換源 和物件的建立來加快源 的執行速度。rvo return value optimization。測試平台 stm32f103vg keil 5.15 背景 我們有個macaddress toarray byte macaddress toarray c...

20 協助完成「返回值優化(RVO)」

19 最後曾提到了在函式通過傳值方式 by value 返回乙個物件時,不可避免地要生成乙個臨時物件,這會嚴重影響到程式的效率,如下例計算兩個分式的乘積 class crational int numer const get numerator int denom const get denomin...