本節書摘來自異步社群出版社《visual c++ 2012 開發權威指南》一書中的第2章,第2.2節,作者: 尹成 , 朱景堯 , 孫明龍 , 胡耀文,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
rvalue引用:n1610"rvalues類對象的初始化的澄清"是早期嘗試啟用無rvalue引用move 語意。
這些新規則還沒有完全實作vc11開發者預覽中。
rvalue引用v3.0添加自動生成的構造函數和移動指派運算符在一定條件下的新規則。這不會進行中vc11,還将繼續遵循的永遠不會自動生成move構造函數/移動頁本頁的行為。
移動語義
rvalue引用支援移動語義的實作,可以顯著提高應用程式的性能。移動語義使能夠調用資源編寫代碼(如動态配置設定的記憶體)來自對象到另一個。移動語義工作,因為它可以使資源從一個程式不能在其他位置引用的臨時對象。
若要實作移動語義,通常會提供一個移動構造函數和(可選)為移動指派運算符(operator=)的類。資料源自動是rvalues構造的副本并配置設定操作利用移動語義。不同于預設複制構造函數,編譯器不提供預設構造函數移動。
還可以重載普通函數和運算符利用移動語義。visual c++2012介紹移動語義到标準模闆庫(stl)。例如,string類實作執行移動語義的操作。考慮連接配接幾個字元串并将結果輸出到的示例:
struct w
{
w(int&, int&) {}
};
struct x
x(const int&, int&) {}
struct y
y(int&, const int&) {}
struct z
z(const int&, const int&) {}
};<code>`</code>
假定需要編寫生成對象的泛型函數。下面的示例示範一種此函數的編寫:
int a = 4, b = 5;
w* pw = factory(a, b);<code>`</code>
但是,下面的示例不包含有效調用factory功能,因為factory作為左值可以使用引用rvalues,可修改的作為其參數,但是,它調用:
<code>z* pz = factory<z>(2, 2);</code>
通常,解決此問題,必須建立factory函數的重載版本a& 和const a& 參數的每種組合。如下面的示例所示,rvalue引用編寫factory功能的版本,例如:
int main()
int a = 4, b = 5;
w* pw = factory(a, b);
x* px = factory(2, b);
y* py = factory(a, 2);
z* pz = factory(2, 2);
delete pw;
delete px;
delete py;
delete pz;
}<code>`</code>
rvalue其他屬性引用
可以重載函數采用了lvalue引用,并且rvalue引用。
通過重載函數采用const lvalue引用或rvalue引用,可以區分不能更改的對象中編寫代碼(lvalue)和可修改的臨時值(rvalues)之間。可以傳遞給采用rvalue引用的功能的對象,除非該對象标記為const。下面的示例示範函數f,重載帶有lvalue引用,并且有rvalue引用。main函數調用與有lvalue和rvalue的函數f。
// named-reference.cpp
// compile with: /ehsc
using namespace std;
//使用記憶體資源的類.
class memoryblock
//在此處為該類添加資源.
void g(const memoryblock&)
cout << "in g(const memoryblock&)." << endl;
}
void g(memoryblock&&)
cout << "in g(memoryblock&&)." << endl;
memoryblock&& f(memoryblock&& block)
g(block);
return block;
g(f(memoryblock()));
該示例産生下面的輸出:
在此示例中,main函數傳遞rvalue到f。f體将其命名參數用作左值。從f的調用。g将參數傳遞給左值引用(g的第一個重載版本)。
可以将左值定義為rvalue引用。
stl std:: 移動功能可以轉換為rvalue的對象對該對象的引用。或者,如下面的示例所示,可以使用static_cast關鍵字左值轉換為rvalue引用,例如:
// template-type-deduction.cpp
template struct s;
// 下面分别制定s為
// lvalue reference (t&), const lvalue reference (const t&),
// rvalue reference (t&&), const rvalue reference (const t&&).
// 每個結構提供輸出函數來輸出每個結構的參數和類型.
template struct s {
static void print(t& t)
{
cout << "print: " << t << endl;
}
static void print(const t& t)
static void print(t&& t)
static void print(const t&& t)
template void print_type_and_value(t&& t)
s::print(std::forward(t));
}
// 此函數傳回字元串 "fourth".
const string fourth() { return string("fourth"); }
string s1("first");
print_type_and_value(s1);
const string s2("second");
print_type_and_value(s2);
// 下面的調用可以解析為:print_type_and_value(string&& t)
print_type_and_value(string("third"));
//下面的調用可以解析為:print_type_and_value(const string&& t)
print_type_and_value(fourth());
若要解決每次調用print_type_and_value函數,編譯器先執行模闆參數推導。會進行相應參數類型轉換時,用模闆參數的編譯器将引用折疊的規則。例如,通過局部變量s1到print_type_and_value函數導緻編譯器生成下列函數簽名:
<code>print_type_and_value<string&>(string& && t)</code>
編譯器使用引用折疊的規則使該簽名減少到以下操作:
<code>print_type_and_value<string&>(string& t)</code>
print_type_and_value功能的此版本向前然後它對s::print方法的正确的專用版本的參數。
下表總結了模闆參數推導類型的引用折疊的規則:
模闆參數推導是實作完全轉發的元素。