令人困惑的return by value

 

問題從這裏開始。
class X;
const X operator+( const X& x1, const X& x2 );
X foo()
{
return X(a+b);
}

X foo()
{
X xx(a+b);
return xx;
}
這兩個函數,有什麼區別?
這個問題牽涉到C++的內部處理,下面是其更通用的模式。
X foo()
{
X xx;
// process
...
return xx;
}
C++如何處理return by value,傳統的方法是修改函數原型。
void foo( X& r )
{
X xx;
xx.X(); //ctor
// process
...
r.XX( xx ) // copy ctor
}
這樣就把xx的值給返回了,這裏有一個xx的臨時對象的ctor和dtor。
於是乎。
X obj = foo();
被轉化爲 
X obj;
foo( obj );
但是,對於程序員來說,是可以進行一些優化的,其方法就是採用ctor返回,
X foo()
{
return X( ... );
}

編譯器處理過後,爲這樣。
void foo( X &r )
{
return r.X(...);
}
看出來了嗎?這裏少個對象(即上面的xx)的ctor和dtor,效率自然提高。
更進一步,如果這個函數是inline的,則
X obj = foo();
被處理成
X obj;
obj.X(...);
Bingo!!
真的是棒呆了,C++注重的效率得以完全體現。
這種優化我稱之爲ARV( anonymous return value )優化,:)
然而對於前者NRV( named return value ),我們又該如何呢?
答案是:沒有辦法,唯一可作的是期待編譯器給我們一些幫助。
如果我們的編譯器夠power的話,那麼
X foo()
{
X xx;
// process
...
return xx;
}
可能被處理成:
void foo( X &r )
{
// ctor
r.X();
// process
...
}
在這裏,同樣沒有出現named object(指xx)的ctor和dtor,但是作爲一個應該把握全局的程序員,我勸你不要太指望它。
首先,它還是調用了default ctor,這在ARV中是不存在的。
其次,你無法知道編譯器是否正在這樣做,畢竟對於廠家來說,它有這樣的權利不讓你知道細節。
再次,編譯器就算有這樣的能力,但僅僅對一些簡單的函數有效,而對於實際編程來說,函數往往很複雜,
比如具有多個分支返回的函數,編譯器就只能嘆氣了。
還有,在函數開頭就聲明對象的作法,可不是正宗C++的style,C++一向提倡“只有在必要是才使用”,真正的C++程序員應該牢記這一點。
最後,從C++編譯器歷史來看,在優化過程中,匿名對象比命名對象更容易消除,你要充分利用它。
答案:
對於這麼一個簡單的函數,如果你的編譯器支持NRV優化,則結果是一樣的,否則。。。
而ARV優化總是支持的。
那採用ARV這樣做有沒有缺點呢?
或許吧,畢竟你要寫一堆ctor用於特殊用途了。:)
注:
本文中的例子選自<<Inside C++ Object Model>>,要感謝Lippman給C++程序員們寫了這麼一本好書,同樣感謝JJhou給中國程序員的翻譯。
本文還參考了MEC(More Effective C++)

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