コンテナとスマートポインタ

昔はよく以下のようなコードを書いていた。

std::vector< boost::shared_ptr< MyInterface > > task;
task.push_back( boost::shared_ptr< MyInterface >( new Task1 ) );
task.push_back( boost::shared_ptr< MyInterface >( new Task2 ) );
task.push_back( boost::shared_ptr< MyInterface >( new Task3 ) );
//↑Task1,Task2,Task3・・・はMyInterfaceを継承している

まあ簡単に言えばコンテナの中にスマートポインタを入れたわけだ。
この実装で、スマートポインタとしてなぜshared_ptrを使ったのか?なぜscoped_ptrではダメなのか?という疑問があるかもしれない。少なくとも当時の私はあった(^^; 答えとしては、vectorはメモリ連続性を保証するため、サイズが変わった場合にメモリをまるごと取り直すことがあり、その際にコピーが発生するのだ。まあそれ以前にpush_backする際に引数にインスタンスを渡すのでそのコピーが発生していたのだ。そういうわけでscoped_ptrは使えなかった。

んで時は流れてVCにもshared_ptrとunique_ptrが取り入れられたのでそちらを使うようになった。んで習慣でやはりコンテナの中身はshared_ptrを用いていた。

あるとき、間違ってコンテナの中身にunique_ptrを使っていたのを発見した。でもそれまで普通にビルドも通り、普通に動いていた。なんでかな?と思ったのだが、そういえばC++11になってから右辺値参照とムーブセマンティクスが出来、またSTLにもそれが取り入れられたわけだ。なのでvectorの中のメモリが取りなおされてもコピーは発生せず、moveされるわけだ。push_backに関しても引数がテンポラリオブジェクトなので右辺値になり、コピーは発生しない。

というわけで、今後はunique_ptrを使っていこうと思う。あ、boost::ptr_vectorを使えというツッコミはなしで(^^;