サンプルの動作確認バージョン [GCC4.4/1.43.0] [VC10/1.43.0]
#include <vector>
#include <iostream>
#include <boost/intrusive_ptr.hpp>
using namespace std;
namespace my
{
class SharedObject
{
private:
SharedObject() : ref_count(1) {}
public:
static SharedObject* create() { return new SharedObject; }
int AddRef() { return ++ref_count; }
int Release() {
if( 0 == --ref_count ) { delete this; return 0; }
return ref_count;
}
void Hello()
{
cout << "hello." << endl;
}
private:
int ref_count;
};
void intrusive_ptr_add_ref( SharedObject* ptr )
{
ptr->AddRef();
}
void intrusive_ptr_release( SharedObject* ptr )
{
ptr->Release();
}
}
int main()
{
typedef boost::intrusive_ptr<my::SharedObject> Ptr;
Ptr p = Ptr(my::SharedObject::create(),false);
vector< Ptr > v;
// vectorに入れたり。
v.push_back( Ptr(my::SharedObject::create(),false) );
v.push_back( Ptr(my::SharedObject::create(),false) );
v.push_back( Ptr(my::SharedObject::create(),false) );
v.push_back( p );
p->Hello();
// pはさっき他にコピーしたけれど、まだここからも参照可能。
return 0;
} // ここで全てdeleteされる。
shared_ptr
の場合、
new
できて delete
できるオブジェクトになら何にでも利用することができます。が、
AddRef
, Release
などのオブジェクト独自の参照カウント機構を活用できない。
など、場合によっては最適な解ではないことがあります。前者の問題は、
オブジェクト自体にカウンタ変数を含めてしまえば一回の割り当てで済むので、
まとめると、「オブジェクトの中に参照カウント計測の仕組みが備わっている場合」
には shared_ptr
とは別のスマートポインタがあると便利かも、
ということになります。そこで intrusive_ptr
。
このクラスは、参照カウントの上げ下げの際に
void intrusive_ptr_add_ref(T * p);
void intrusive_ptr_release(T * p);
の二つの関数のみを利用します。ので、自分の使うオブジェクトに応じて、 この二つを用意して適切にカウント上げ下げや削除を行えばOK。例えばCOMなら
void intrusive_ptr_add_ref(IUnknown* p) { p->AddRef(); }
void intrusive_ptr_release(IUnknown* p) { p->Release(); }
みたいに定義しておいて利用します。