C++11中std:move()的作用和用法

官方文檔:http://www.cplusplus.com/reference/utility/move/?kw=move

功能:返回傳入參數的右值引用。右值引用的概念是在C++11才提出來的。在此之前只有一種引用。

優點:調用此函數不會引起任何數據爭用。(Calling this function introduces no data races.)

說明:

This is a helper function to force move semantics on values, even if they have a name: Directly using the returned value causes arg to be considered an rvalue.

Generally, rvalues are values whose address cannot be obtained by dereferencing them, either because they are literals or because they are temporary in nature (such as values returned by functions or explicit constructor calls). By passing an object to this function, an rvalue that refers to it is obtained.

Many components of the standard library implement move semantics, allowing to transfer ownership of the assets and properties of an object directly without having to copy them when the argument is an rvalue.

Although note that -in the standard library- moving implies that the moved-from object is left in a valid but unspecified state. Which means that, after such an operation, the value of the moved-from object should only be destroyed or assigned a new value; accessing it otherwise yields an unspecified value.

通常,右值是其地址無法通過解引用獲得的值,因爲它們是文字或本質上是臨時的(例如,函數或顯式構造函數返回的值)。 通過將對象傳遞給此函數,可以獲得引用該對象的右值。

標準庫的許多組件都實現了移動語義,允許直接轉移對象的資產和屬性的所有權,而在參數爲右值時無需複製它們。

要注意-在標準庫中-移動意味着從中移出的對象處於有效但未指定的狀態。 這意味着在執行此操作後,僅應銷燬移出對象的值或爲其分配新值; 否則訪問它會產生未指定的值。

看例子代碼:

// move example
#include <utility>      // std::move
#include <iostream>     // std::cout
#include <vector>       // std::vector
#include <string>       // std::string

int main () {
  std::string foo = "foo-string";
  std::string bar = "bar-string";
  std::vector<std::string> myvector;

  myvector.push_back (foo);                    // copies
  myvector.push_back (std::move(bar));         // moves

  std::cout << "myvector contains:";
  for (std::string& x:myvector) std::cout << ' ' << x;
  std::cout << '\n';
  
  std::cout << "foo:"<<foo<<'\n';
  std::cout << "bar:"<<bar<<std::endl;

  return 0;
}

輸出結果如下:

myvector contains: foo-string bar-string
foo:foo-string
bar:

看到move的作用了吧.

看看如果不用std::move()對比一下:

// move example
#include <utility>      // std::move
#include <iostream>     // std::cout
#include <vector>       // std::vector
#include <string>       // std::string

int main () {
  std::string foo = "foo-string";
  std::string bar = "bar-string";
  std::vector<std::string> myvector;

  myvector.push_back (foo);                    // copies
  myvector.push_back (bar);         // moves

  std::cout << "myvector contains:";
  for (std::string& x:myvector) std::cout << ' ' << x;
  std::cout << '\n';
  
  std::cout << "foo:"<<foo<<'\n';
  std::cout << "bar:"<<bar<<std::endl;

  return 0;
}

輸出結果如下:

myvector contains: foo-string bar-string
foo:foo-string
bar:bar-string

參考中對於這個例子的解釋:

The first call to myvector.push_back copies the value of foo into the vector (foo keeps the value it had before the call).
The second call moves the value of bar into the vector. This transfers its content into the vector (while bar loses its value, and now is in a valid but unspecified state).

第一次調用myvector.push_back會將foo的值複製到向量中(foo保留調用前的值)。
第二次調用將bar的值移動到向量中。 這會將其內容傳輸到向量中(而bar失去其值,並且現在處於有效但未指定的狀態)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章