CPPの右辺値参照・ムーブセマンティクス〜その3〜
前回の投稿で「ムーブ」の意味があやふやなままになってしまったので、ここで探ってみる。スマートポインタを使うが、それについては深く触れない。
struct hoge { std::shared_ptr<int> ptr; hoge(int val):ptr(new int(val)) {}; int getCount() { return ptr.use_count(); } void release() { ptr.reset(); } };
という状況で、
hoge Hoge1(1); hoge Hoge2(Hoge1); hoge Hoge3(Hoge2); std::cout << Hoge3.getCount() << std::endl; // => 3 Hoge2.release(); std::cout << Hoge3.getCount() << std::endl; // => 2
となるが、一方で、
hoge Hoge1(1); hoge Hoge2(std::move(Hoge1)); hoge Hoge3(Hoge2); std::cout << Hoge3.getCount() << std::endl; // => 2 Hoge2.release(); std::cout << Hoge3.getCount() << std::endl; // => 1
となる。move関数によって、ポインタの所有権が渡されている(ムーブ)。このとき、オブジェクトのコピーは行われていないので、効率が良いという利点がある。ただし、一度所有権を渡すと、そのあとにオブジェクトを参照したり、deleteしたりしてはいけない。
unique_ptrにおいては、
struct hoge { std::unique_ptr<int> ptr; hoge(int val):ptr(new int(val)) {}; void release() { ptr.release(); } };
という状況で、
hoge Hoge1(1);
hoge Hoge2(Hoge1);
とすると、
error: call to implicitly-deleted copy constructor of 'hoge' hoge Hoge2(Hoge1);
というエラーが出る。これは、unique_ptrは所有者が一人だけでないといけないため、コピーして所有者を増やすことができないために起きる。(それを実現するためにコピーコンストラクタを消している?)一方、
hoge Hoge1(1);
hoge Hoge2(std::move(Hoge1));
としても、エラーは出ない。これは、所有者を移しているだけなので、所有者は一人のままだからだ。これもムーブコンストラクタをうまく定義することで実現している?