shared_ptrの実装5

shared_ptr< void >で任意のインスタンスをdeleteする

前回のshared_ptrの実装4 - while( c++ );

    shared_ptr< void > a( new int( 100 ) );

とすると、デストラクタで正しくdeleteされません。今日はこれを解決しましょう。

問題になっているのは

  • delete void*;

です。型がわからないとdeleteできません。

template < typename T >
class shared_ptr
{
...

public:
    explicit shared_ptr( T* ptr )
    : ptr( ptr )
    , count( ptr )
    {}

...
};
  • コンストラクタでT*を渡しているので、中の人shared_countが管理しているptrがT*になってしまう。

ということは、任意の型のポインタを保持するために、コンストラクタをテンプレートにすればよいわけですね。

template < typename T >
class shared_ptr
{
...

public:
    template < typename U >
    explicit shared_ptr( U* ptr )
    : ptr( ptr )
    , count( ptr )
    {}

...
};

これだけでOKです。クラスを渡してもちゃんとデストラクタが呼ばれてます。

    class Hoge
    {
    public:
        ~Hoge(){ cout << "~Hoge()" << endl; }
    };


    shared_ptr< void > a( new Hoge );

さらに、派生クラスのポインタを渡すことが可能になります。

    class Hoge
    {
    public:
        ~Hoge(){ cout << "~Hoge()" << endl; }//virtualが付いていなくても良い
    };
    class Piyo : public Hoge
    {
    public:
        ~Piyo(){ cout << "~Piyo()" << endl; }
    };


    shared_ptr< Hoge > a( new Piyo );

基底のデストラクタが仮想デストラクタになっていなくても正しくdeleteされます。

アップキャスト

同様にコピーコンストラクタもテンプレートにしましょう。

template < typename T >
class shared_ptr
{
...

public:
    template < typename U >
    shared_ptr( shared_ptr< U > const& sp )
    : ptr( sp.ptr )
    , count( sp.ptr )
    {}

...
};

コンパイルすると、

error C2248: sahred_ptr<T>::ptr : privateメンバにアクセスできません。

怒られました。。。

templateclass shared_ptrをfriendにしましょう。

template < typename T >
class shared_ptr
{
    template < typename U > friend class shared_ptr;

...
};

これで、アップキャストも可能になりました。

    shared_ptr< Piyo > a( new Piyo );
    shared_ptr< Hoge > b = a;
    shared_ptr< void > c = a;

ポインタらしくなってきましたね。