程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Return Value Optimization(RVO)返回值優化

Return Value Optimization(RVO)返回值優化

編輯:關於C語言
 

通過C99的一些標准,我們發現,其實C語言並不是一門設計非常精細的語言,不是按照人類的思考方式去設計的,其中有很多東西似乎都沒有進行精心的設計,其中最典型的就是關於字符串常量的定義,模糊不清。那麼到後來,直到Bjarne Stroustrup基於C語言引入面向對象的概念,發明了C++。而C++似乎更符合人類的思維邏輯,C++應該說是更加開放,雖然C++也提出了封裝的概念,但是C++並不是一門安全的語言。我對於這些知識的理解,應該說都是從WebKit的C++源碼中領悟出來的。

最近在深入研究Webkit中的智能指針的時候,發現WebKit的智能指針中有提到關於Return Value Optimization(RVO)返回值優化對於智能指針的效率的影響。今天就來講一講我對於Return Value Optimization的理解

按照慣例,我們還是從一個Demo開始

// main.cpp

#include <stdlib.h>
#include <iostream>

using namespace std;

class Dog {
public:
Dog()
{
cout << "I in Dog Constructor" << endl;
}

Dog(const Dog& dog)
{
cout << "I am in Dog copy Constructor" << endl;
}

~Dog()
{
cout << "~Dog Destructor" << endl;
}
};

Dog getDog() {
Dog d = Dog();
return d;
}

int main(int argc, char** argv)
{
Dog d = getDog();

return 0;
}

這段代碼在g++和VS2010中不加任何特殊的參數,編譯運行的結果有所不同

Ubuntu下運行結果如下:

I in Dog Constructor
~Dog Destructor

在VS2010中輸出的結果如下:

I in Dog Constructor
I am in Dog copy Constructor
~Dog Destructor
~Dog Destructor

根據C++標准Rvaluereferencesandmoveconstructors,允許編譯器針對拷貝構造函數的調用進行優化,在某些情況下,甚至可以消除或者減少對拷貝構造函數的調用。

我們在g++編譯這個demo程序的時候,添加參數-fno-elide-constructors禁用返回值優化,來看看,在不做優化的情況下,編譯執行的情況:

I in Dog Constructor
I am in Dog copy Constructor
~Dog Destructor
I am in Dog copy Constructor
~Dog Destructor
I am in Dog copy Constructor
~Dog Destructor
~Dog Destructor

Oops! 我想你跟我一樣,看到這個結果會瘋掉。如果這麼簡單的邏輯,拷貝構造函數的調用會如此頻繁,那的確對於WebKit中的智能指針的效率影響很大,因為頻繁的調用拷貝構造函數會造成refcount被頻繁的加一減一。

Walter Bright最先是在Zortech C++中實現的優化方案實例如下:

struct Data {
char bytes[16];
};

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

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

那麼類比到我們的Dog中,代碼編譯優化之後 應該是這樣的

int main(int argc, char** argv)
{
Dog d;
getDog(&d);
// ..
}

優化之後,省去了拷貝構造函數的調用。Walter Bright的這種編譯器優化技術就是Named return value optimization。顯然g++編譯器也運用了此優化。而VS2010中,卻出現了一次調用,我個人理解應該是VS中getDog傳進來的對象的引用而不是指針,所以會造成有一次拷貝構造函數的調用。
 

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved