C++11在運行期有所增強,通過增加核心的右值引用機制來改善臨時對象導致的效率低下的問題。C++臨時對象引入了多余的構造、析構及其內部資源的申請釋放函數調用,導致程序運行時性能受損,這一點被廣為詬病。C++標准委員會在C++11中引入了右值引用這個核心語言機制,來提升運行期性能。右值引用機制要能發揮威力,需要多種設施支持。這里說一下其中的一個,標准庫中的std::move模板方法。move語義涉及的代碼很少,如下所示,我用的是vc10.0版本的STL庫。
template<class _Ty> inline typename remove_reference<_Ty>::type&& move(_Ty&& _Arg) _NOEXCEPT { // forward _Arg as movable return ((typename remove_reference<_Ty>::type&&)_Arg); } template<class _Ty> struct remove_reference { // remove reference typedef _Ty type; }; template<class _Ty> struct remove_reference<_Ty&> { // remove reference typedef _Ty type; }; template<class _Ty> struct remove_reference<_Ty&&> { // remove rvalue reference typedef _Ty type; };
基於上面的代碼,可以看出move語用是把變量強制轉換成右值引用。既然理解了這個語用,我們可以不使用move函數來為需要右值引用的函數傳遞參數,在代碼中可以直接使用“(_Ty&&)變量”的形式。可是,我們應該使用move函數而避免使用上述的強制轉換,主要是基於下面的幾點。
1:標准庫中的move函數為轉換成右值提供了一層抽象,能夠更適應未知的未來。
2:標准庫中的move函數只有很少的代碼,性能會比之前的深度拷貝更好。
3:如果我們改變了變量的類型,產生右值引用的表達式可以不用改變。
4:相比int &&,move所寫的字符很少。
從 template<class _Ty> struct remove_reference<_Ty&&>來看,move支持應用在右值引用類型變量上。一個右值引用變量傳遞到需要右值引用的函數中去,是否還需要move語句呢?照以前經驗來推斷的話,會覺得不必要了。實際上是必需的,考察下面的代碼。
bool IsRvalue(const int&& ) { return true; } bool IsRvalue(int &) { return false; } bool IsRvalue(const int& ) { return false; } //bool IsRvalue(int ) //{ // return false; //} void Test(int &&rv) { printf("rv is a rvalue: %s\n", IsRvalue(rv)? "yes": "no"); printf("rv is a move(rvalue): %s\n", IsRvalue(move(rv))? "yes": "no"); } int _tmain(int argc, _TCHAR* argv[]) { int i = 5; Test(move(i)); system("pause"); return 0; }
運行上面的代碼會發現IsRvalue(rv)會調用IsRvalue(int &)函數,究其原因是右值引用象引用一樣,也是引用一個對象,在Test函數體中rv是一個引用。右值引用主要用於引用函數返回的臨時對象,以期能夠修改它來避免內部資源的深度拷貝。
5:既使是把一個右值引用對象匹配參數中的右值引用也必須使用move語句。