サンプルの動作確認バージョン [GCC4.4/1.41.0] [VC9/1.41.0]
#include <string>
#include <vector>
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
int main()
{
typedef boost::shared_ptr<string> StrPtr;
StrPtr s = StrPtr(new string("pen"));
vector< StrPtr > v;
// vectorに入れたり。
v.push_back( StrPtr(new string("this")) );
v.push_back( StrPtr(new string("is")) );
v.push_back( StrPtr(new string("a")) );
v.push_back( s );
cout << *s << endl; // sをpush_backで他にコピーしたからと言って使えなくなったりしない
return 0;
} // ここで全てdeleteされる。
使わなくなったオブジェクトを自動で delete
してくれる、スマートポインタです。
同じオブジェクトを指している shared_ptr
変数の個数が裏で自動的にカウントされて、
ゼロになると、つまりどの変数からもオブジェクトが参照されなくなると、
その瞬間に delete
が呼ばれます。
この参照回数カウント機能が、
scoped_ptr
や標準の std::auto_ptr
との違い。複数のオブジェクトから同時に参照されるような共有オブジェクトの
delete
も上手くやってくれます。
auto_ptr
shared_ptr
!
と言ったところでしょうか。
また、vector
等のコンテナはオブジェクトの移動ではなくコピーを前提としているため
auto_ptr
を入れられないという欠点がありましたが、shared_ptr
は大丈夫というのも利点。C++98 の標準ライブラリにはいってないのが疑問なくらい汎用性アリです。
auto_ptr
は使わず全て shared_ptr
で置き換えてもいいのではないかと個人的には思います。
scoped_ptr
も無しで全部 shared_ptr
で統一しちゃう派の人もいるようです。
ただし、一般的なガベージコレクションと違って、
shared_ptr
で循環参照が発生すると正しく delete
できなくなってしまいますので、
そこだけ注意が必要です。あまりなんでもかんでも shared_ptr
にしすぎないこと。
スマートポインタは、「オブジェクトが、
自分が"所有"しているオブジェクトを指すための変数」にだけ使用します。
所有関係ではないただの参照関係のための変数は、普通のポインタです
(weak_ptr
の方が適切なこともたまにあります)。
たいていの場合は…特にオブジェクト指向的に設計をしている場合は、
変数が所有関係を表しているかそうでないかは比較的明らかなはず。
それをそのままコードに落とせばOKです。
どのオブジェクトがどのオブジェクトを所有していると言えるのか定かでないようなコードの場合は、
闇雲に shared_ptr
にするよりは、
根本的に設計を見直すか、おそらく BoehmGC などの GC を使うべきでしょう。
Cryolite 氏による以下の記事は必読です!