導入
大きなデータを「コピー」するのは無駄なことがあります。もう使わない一時オブジェクトなら、中身を「移す(ムーブ)」だけで十分です。C++11 で入った「ムーブセマンティクス」は、モダン C++ の性能を支える重要な仕組みです。
説明
カギは「rvalue 参照 型&&」です。名前のない一時オブジェクト(右辺値)を受け取り、その中身を奪って(ポインタを付け替えて)自分のものにします。コピーのように複製しないので高速です。
flowchart LR a["コピー:中身を丸ごと複製<br/>元も残る(遅い)"] b["ムーブ:ポインタを付け替えるだけ<br/>元は空になる(速い)"] a -->|"一時オブジェクトなら"| b
#include <iostream>
#include <utility> // std::move
using namespace std;
class Buffer {
int* data;
int size;
public:
Buffer(int n) : data(new int[n]()), size(n) {}
// ムーブコンストラクタ:other から資源を奪う
Buffer(Buffer&& other) noexcept : data(other.data), size(other.size) {
other.data = nullptr; // 元は空に(デストラクタで二重解放しないため)
other.size = 0;
cout << "ムーブされた" << endl;
}
~Buffer() { delete[] data; }
int getSize() const { return size; }
};
int main() {
Buffer a(1000);
Buffer b = std::move(a); // a をムーブ(コピーしない)
cout << b.getSize() << endl; // 1000
cout << a.getSize() << endl; // 0(中身は b に移った)
return 0;
}
std::move は「この値はもう使わないので、ムーブしてよい」という目印です(実際に動かすわけではなく、rvalue 参照に変換するだけ)。vector に大きな要素を入れるときなどに、内部で自動的にムーブが使われて高速化されています。
まとめ
ムーブは「中身を複製せず移す」高速な受け渡しです。型&&(rvalue 参照)で受け取り、std::move で明示的にムーブできます。移した後の元オブジェクトは「空だが破棄はできる」状態にしておくのが約束です。