今回はC++11で導入され
ムーブ・セマンティクスについて紹介します。ムーブセマンティクスとは結論から言ってしまえば無駄なコピーをせずに所有権を譲るということです。しかし、イメージではわかりにくいので実際にどのように使うか、どのくらい便利なのかをコードで紹介したいと思います。
//全ての値を2倍する int addNum(std::vector<int> a) { for (auto& value : a) value *= 2; return std::move(a); //所有権を返却 } //とても巨大なコンテナ std::vector<int> vec={/* ......... */}; //なにも工夫しない場合(コピー発生) addNum(vec); //ムーブセマンティクスの場合(所有権の転移) addNum(std::move(vec));
普通にコンテナを渡した場合には当然コピーが発生します。コンテナが巨大な場合コピーコストはとても無駄です。そこで所有権を渡して、処理が終わったら所有権を返してもらうようにすることで無駄なコピーを発生しなくしています。例のコード程度なら参照渡しを使えばいいんじゃないかと思う方もいると思いますが、このような処理は同時にムーブセマンティクスの出番でもあるのです。
しかしここでふと疑問に気付きます。所有権を渡した変数の中身にはなにが残っているのか。答えはわからないです。C++11ではムーブセマンティクスで所有権を移動させた元変数は有効だが中身は未定義とされています。つまり、その後代入などして使うことはできるが現段階で中身に何がはいっているかは不明ということです。
今回は関数への引数として渡しましたが直接所有権を渡す場合にはこのようにします。
int* a; a=std::move(b);
ちなみに代入演算子がない状態で実行(つまり、std::move(b)単体)した場合にはなにも起こりません。ただの無意味なコードとなります。
説明を省略してきましたがムーブセマンティクスは概念自体が「右辺値参照」と似ており組み合わせて使うため一緒によく紹介されますが厳密には区別されています。右辺値参照について詳しく知りたい方は検索してみるとたくさんありますのでそちらをご覧ください。