Named Return Value Optimization

  已知下列函數定義:

X bar() {
    X xx;
    // process xx ...
    return xx;
}

  你可能會問bar()的返回值如何從局部對象xx中拷貝過來?

實現模型1

返回值的初始化(Return Value Initialization)

  Stroustrup在cfront中的解決做法是一個雙階段轉化:

  1. 首先加上一個額外參數,參數類型是對對象的引用,用來存放返回結果;
  2. 在return指令之前安插一個copy constructor調用操作,對這個參數利用返回值進行拷貝初始化。

  根據上述算法,bar()的轉換如下:

// function transformation to reflect
// application of copy constructor
// Pseudo C++ Code
void bar( X& __result )
{
   X xx;

   // compiler generated invocation

   // of default constructor

   xx.X::X();

   // ... process xx

   // compiler generated invocation

   // of copy constructor

   __result.X::X( xx );

   return;

}

實現模型2

在編譯器層面做優化(Optimization at the Compiler Level)

  Named Return Value (NRV) optimization,具名返回值優化。
  在一個像bar()這樣的函數中,所有的return指令傳回相同的具名數值,因此編譯器有可能自己做優化,方法是:以result參數取代named return value。
  根據這個方法,bar()的轉換如下:

//__result is substituted for xx by the compiler:
void bar( X &__result )
{

   // default constructor invocation

   // Pseudo C++ Code

   __result.X::X();

   // ... process in __result directly

   return;

} 

Named Return value 優化:
  NRV優化的本質是優化掉拷貝構造函數。在實現模型1中我們看到了,返回對象的實現總是先對某個對象進行操作,操作完成後,使用Copy Constructor將操作後的對象內容複製到另外一個對象中,然後返回。 基於這樣一個前提,NRV可以調用Copy Constructor這一步被省掉。所以NRV的前提必須要有Copy Constructor。
  NRV也有副作用,就是Copy Constructor中的代碼不會被執行。

【注意】一方面要考慮默認的語義是否符合我們的需要。另一方面如果對象面臨大量的拷貝操作[ 比如這個class的object需要經常以傳值的方式返回],有必要實現一個拷貝構造函數以支持NRV優化。但是如果想使用底層的memcpy之類的直接進行bit wise copy,注意是否真的是bit wise copy拷貝,比如如果是virtual,這樣可能破壞調vptr。

發佈了129 篇原創文章 · 獲贊 45 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章