C++11 における std:move() の役割と使用法

公式ドキュメント: http://www.cplusplus.com/reference/utility/move/?kw=move

機能: 受信パラメータの右辺値参照を返します。右辺値参照の概念は、C++11 でのみ提案されました。それまでは引用は 1 種類しかありませんでした。

長所: この関数を呼び出しても、データ競合は発生しません。(この関数を呼び出してもデータ競合は発生しません。)

注釈:これは、値に名前がある場合でも、値に移動セマンティクスを

強制するヘルパー関数です 。戻り値を直接使用すると、 arg がrvalue とみなされます 一般に、右辺値は、リテラルであるか、本質的に一時的なものであるため (関数や明示的なコンストラクター呼び出しによって返される値など)、逆参照によってアドレスを取得できない値です。この関数にオブジェクトを渡すと、  それを参照する右辺値が取得されます。標準ライブラリの多くのコンポーネントは 、移動セマンティクスを実装しており、引数が右辺 値である場合に、オブジェクトのアセットとプロパティの所有権をコピーすることなく直接譲渡できます。





ただし、標準ライブラリでは、 移動とは、移動元の オブジェクトが有効ではあるが未指定の状態のままであること を意味します 。つまり、このような操作の後は、 移動元 オブジェクトの値は破棄されるか、新しい値が割り当てられるだけである必要があります。それ以外の場合にアクセスすると、不特定の値が返されます。

一般に、右辺値は、本質的にリテラルまたは一時的なものであるため、逆参照によってアドレスを取得できない値です (たとえば、関数または明示的なコンストラクターによって返される値)。この関数にオブジェクトを渡すと、そのオブジェクトを参照する右辺値を取得できます。

標準ライブラリの多くのコンポーネントは移動セマンティクスを実装しており、オブジェクトのアセットとプロパティの所有権を、引数が右辺値の場合にコピーせずに直接転送できるようにします。

標準ライブラリでは、移動とは、移動元のオブジェクトが有効ではあるが未指定の状態にあることを意味することに注意してください。これは、この操作の後、オブジェクトから移動された値のみを破棄するか、新しい値を割り当てる必要があることを意味します。それ以外の場合は、その値にアクセスすると、不特定の値が生成されます。

コード例を見てください。

// 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

この例の説明はリファレンスにあります。

の最初の呼び出しでは、  myvector.push_back foo の値がベクトルにコピーされます (foo は呼び出し前の値を保持します)。
2 番目の呼び出しでは、bar の値をベクトルに移動します。これにより、その内容がベクトルに転送されます (一方、bar はその値を失い、現在は有効ですが未指定の状態になります)。

myvector.push_back への最初の呼び出しでは、foo の値がベクトルにコピーされます (foo は呼び出し前の値を保持します)。
2 番目の呼び出しでは、bar の値をベクトルに移動します。これにより、その内容がベクトルに転送されます (一方、bar は値を失い、現在は有効ですが未指定の状態になります)。

おすすめ

転載: blog.csdn.net/grf123/article/details/105379337