14
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

std::moveは使用上の注意をよく読み、用法・用量を守って正しくお使い下さい。

Last updated at Posted at 2017-06-20

要約: std::move()は「オブジェクト構築/代入操作においてムーブセマンティクス(move semantics)を明示するため」のものであり、それ以外の場面で用いるべきでない。という主張。

正しい使い方
FooClass x;
FooClass y{std::move(x)};  // xからyへムーブ操作

FooClass z;
z = std::move(y);          // yからzへムーブ操作

不適切事例1

適切でない使い方1
FooClass x;

// std::move戻値を右辺値参照型rxに束縛しておき...
FooClass&& rx = std::move(x);

// あとでrxから"ムーブ"するつもり??
FooClass y = rx;

右辺値参照型の変数 rx をどう利用するつもりでした?あなたの期待に反して FooClass y = rx; は "ムーブ操作" ではなく "コピー操作" になります。rx(つまりx)から "ムーブ操作" を行う場合は、

FooClass y = std::move(rx);

のように、結局は rx に対しても std::move を明示する必要があります。何のために右辺値参照型(FooClass&&)を使ったんでしたっけ?

不適切事例2

適切でない使い方2
FooClass x, y;

// std::move戻値に別オブジェクトを代入??
std::move(x) = y;

このコードで行われる処理は、単純なコピー代入操作(x = y;)と等価です。つまりこのstd::moveは、善良なプログラマを惑わすだけの冗長なシロモノです。やめときましょう。

重箱の隅: コピー代入演算子を operator=(const T&) &operator=(T&) && でオーバーロード定義すれば、x = y; で前者を std::move(x) = y; で後者をと呼び分けることはできます。ただし(私が知る限り)、後者のセマンティクスについて広く合意されたものはないため、あくまでも自己責任でどうぞ。

やる気の無い解説

  • std::move関数 それ自身は、何の処理も行いません
  • std::move関数は、型キャスト(type cast) しか行いません。
  • 実際の "ムーブ操作" 処理を行うのは、構築/代入対象となるクラス自身です。
  • 関数名moveが示すとおり、「ムーブセマンティクス」をソースコード上で明示するラベル に過ぎません。
  • C++文法上は、明示的な型キャストにより "ムーブ操作" を行えます。std::move関数は必須ではありませんが、分かりやすさのため 利用が強く推奨されます。
14
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?