天天看點

《Visual C++ 2012 開發權威指南》——2.2 Visual C++2012的語言新特性(2)include include include

本節書摘來自異步社群出版社《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&lt;z&gt;(2, 2);</code>

通常,解決此問題,必須建立factory函數的重載版本a&amp; 和const a&amp; 參數的每種組合。如下面的示例所示,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&amp;)

  cout &lt;&lt; "in g(const memoryblock&amp;)." &lt;&lt; endl;

}

void g(memoryblock&amp;&amp;)

  cout &lt;&lt; "in g(memoryblock&amp;&amp;)." &lt;&lt; endl;

memoryblock&amp;&amp; f(memoryblock&amp;&amp; block)

  g(block);

  return block;

  g(f(memoryblock()));

該示例産生下面的輸出:

《Visual C++ 2012 開發權威指南》——2.2 Visual C++2012的語言新特性(2)include include include

在此示例中,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&amp;), const lvalue reference (const t&amp;),

// rvalue reference (t&amp;&amp;), const rvalue reference (const t&amp;&amp;).

// 每個結構提供輸出函數來輸出每個結構的參數和類型.

template struct s {

  static void print(t&amp; t)

  {

   cout &lt;&lt; "print: " &lt;&lt; t &lt;&lt; endl;

  }

  static void print(const t&amp; t)

  static void print(t&amp;&amp; t)

  static void print(const t&amp;&amp; t)

template void print_type_and_value(t&amp;&amp; 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&amp;&amp; t)

  print_type_and_value(string("third"));

  //下面的調用可以解析為:print_type_and_value(const string&amp;&amp; t)

  print_type_and_value(fourth());

《Visual C++ 2012 開發權威指南》——2.2 Visual C++2012的語言新特性(2)include include include

若要解決每次調用print_type_and_value函數,編譯器先執行模闆參數推導。會進行相應參數類型轉換時,用模闆參數的編譯器将引用折疊的規則。例如,通過局部變量s1到print_type_and_value函數導緻編譯器生成下列函數簽名:

<code>print_type_and_value&lt;string&amp;&gt;(string&amp; &amp;&amp; t)</code>

編譯器使用引用折疊的規則使該簽名減少到以下操作:

<code>print_type_and_value&lt;string&amp;&gt;(string&amp; t)</code>

print_type_and_value功能的此版本向前然後它對s::print方法的正确的專用版本的參數。

下表總結了模闆參數推導類型的引用折疊的規則:

《Visual C++ 2012 開發權威指南》——2.2 Visual C++2012的語言新特性(2)include include include

模闆參數推導是實作完全轉發的元素。