2011年6月17日金曜日

終・スマートポインタの別の解

さて、前回は weak_ptr は使わずに新しいクラス distributable_ptr を作成しました。実現したいことは、weak_ptr に近いんですが shared_ptr を必要としないというところがミソなわけです。

で、その構造を見てもらうとわかるんですが、参照数をカウントしておいて、なくなったら削除するという仕組みはスマートポインタとまったく一緒です。じゃあ、distributed_ptr は shared_ptr としても機能するのでは?とも考えられます。

で、distributed_ptr に shared_ptr として機能させるためのコンストラクタを追加し、デストラクタにも処理を追加します。
template <class T>
distributed_ptr<T>::distributed_ptr( distributable_ptr<T>* org )
  : data( org->data )
{ // このコンストラクタを使用した場合はスマートポインタモードになります。
  // data が持っている distributable_ptr が最初に +1 した参照数は、この
  // ポインタが参照したことにし、distributable_ptr 自体は weak_ptr のよう
  // に参照数を +1 していないものと考えます。
}

template <class T>
distributed_ptr<T>::~distributed_ptr( void )
{ // スマートポインタモードの時、最後の distributed_ptr が破棄されると、
  // 参照数が 0 になります。
  // スマートポインタモードでなければ、distributable_ptr が参照数 1 を
  // 保持していますので、すべての distributed_ptr が破棄されても参照数は
  // 0 にはなりません。
  T*  ptr = this->data->get();
  if( !distributable_data<T>::dereference( this->data ) )
      delete ptr;
}
この追加によって、distributed_ptr は shared_ptr としても機能することになります。つまり、
class Hoge : public distributable_ptr<Hoge>
{
public :
    Hoge( void ) {}
    virtual ~Hoge( void ) {}
};

void foo()
{
    distributed_ptr<Hoge>  ptr( new Hoge );
    ... 処理 ...
}
のように shared_ptr っぽい書き方をするとスマートポインタとして機能し、関数 foo() を抜ける際にはちゃんと Hoge のインスタンスが破棄されるようになります。当然、前回書いたような機能もそのまま使えます。この distributable_ptr 及び distributed_ptr の特徴としては
・shared_ptr + weak_ptr よりも構築が簡単で安全。
・スタックで確保しても、配列で確保しても、new で確保しても構わない。
・スマートポインタで管理するかどうかは任意に選ぶことができる。
・weak_ptr のように自身のポインタを distributed_ptr として配布する事ができる。
といった所でしょうか。ただ、自身のポインタを外部に配布する必要がない場合には不要となる機能が多いので、shared_ptr をすべてこれに置き換えればいいというものでもありません。

shared_ptr の代わりとして使うには機能がまだまだ足りませんが、いろいろ機能付け足してテストもして後日公開したいと思います。

0 件のコメント:

コメントを投稿