返回值優化

返回值優化(Return value optimization,縮寫為RVO)是C++的一項編譯優化技術。即刪除保持函數返回值的臨時對象。這可能會省略兩次複製構造函數,即使複製構造函數有副作用。[1] [2]

典型地,當一個函數返回一個對象實例,一個臨時對象將被創建並通過複製構造函數把目標對象複製給這個臨時對象。C++標準允許省略這些複製構造函數,即使這導致程序的不同行為,即使編譯器把兩個對象視作同一個具有副作用。 [3]

#include <iostream>

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
  return C();
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f();
}

對於函數返回類對象,一種實現辦法是在函數調用語句前在stack frame上聲明一個隱藏對象,把該對象的地址隱蔽傳入被調用函數,函數的返回對象直接構造或者複製構造到該地址上。[4]例如:

struct Data { 
  char bytes[16]; 
};

Data f() {
  Data result = {};
  // generate result
  return result;
}

int main() {
  Data d = f();
}

可能產生的代碼如下:

struct Data { 
  char bytes[16]; 
};

Data * f(Data * _hiddenAddress) {
  Data result = {};
  // copy result into hidden object
  *_hiddenAddress = result;
  return _hiddenAddress;
}

int main() {
  Data _hidden; // create hidden object
  Data d = *f(&_hidden); // copy the result into d
}

這引起了Data對象被複製兩次。

另一種技術是命名返回值優化(Named return value optimization,NRVO)。[5]NRVO去除了基於棧的返回值的構造與析構。雖然這會導致優化與未優化的程序的不同行為。

struct Data { 
  char bytes[16]; 
};

void f(Data *p) {
  // generate result directly in *p
}

int main() {
  Data d;
  f(&d);
}

大部分C++編譯器均支持返回值優化。[1][6][7]在某些環境下,編譯器不能執行此優化。一個常見情形是當函數依據執行路徑返回不同的命名對象,或者命名對象在asm內聯塊中被使用:[4][6][8]

#include <iostream>

struct C {
	C(int j) { i = j; }
	C(const C&) { std::cout << "A copy was made.\n"; }

	int i;
};

C  f(bool cond = false) {
	C first(101);
	C second(102);
	// the function may return one of two named objects
	// depending on its argument. RVO might not be applied
	return cond ? first : second;
}

int main() {
	std::cout << "Hello World!\n";
	C obj = f(true);
}

參見

參考文獻

  1. ^ 1.0 1.1 Meyers, Scott. More Effective C++. Addison Wesley. 1996. 
  2. ^ Alexandrescu, Andrei. Move Constructors. Dr. Dobbs Journal. 2003-02-01 [2009-03-25]. (原始內容存檔於2013-07-14). 
  3. ^ C++98標準的節12.8.「Copying class objects」第15段
  4. ^ 4.0 4.1 Bulka, Dov; David Mayhew. Efficient C++. Addison-Wesley. 2000. ISBN 0-201-37950-3. 
  5. ^ Glossary D Programming Language 2.0. Digital Mars. [2009-03-23]. (原始內容存檔於2013-07-14). 
  6. ^ 6.0 6.1 Shoukry, Ayman B. Named Return Value Optimization in Visual C++ 2005. Microsoft. [2009-03-20]. (原始內容存檔於2013-07-14). 
  7. ^ Options Controlling C++ Dialect. GCC. 2001-03-17 [2009-03-20]. (原始內容存檔於2013-07-14). 
  8. ^ Hinnant, Howard; et al. N1377: A Proposal to Add Move Semantics Support to the C++ Language. WG21. 2002-09-10 [2009-03-25]. (原始內容存檔於2009-03-01).