shared_ptrの実装3
前回の続き
では、実際に参照カウンタ式のスマートポインタを作ってみましょう。
参照カウンタを追加
たとえば以下のような場合、new intの実体と参照数が共有されるので、参照カウンタも動的に作らないといけませんね。
shared_ptr< int > a( new int( 100 ) ); //参照カウンタ=1 shared_ptr< int > b = a; //参照カウンタ=2
template < typename T > class shared_ptr { private: T* ptr; int* count; //reference counter public: shared_ptr() : ptr( 0 ) , count( 0 ) {} shared_ptr( T* ptr ) : ptr( ptr ) , count( new int( 1 ) ) {} ...省略 };
- コンストラクタで生のポインタを受け取ったとき、参照数を1として参照カウンタを生成
boostの場合、shared_countという参照カウンタクラスを使っていますが、今回は使わない方向で。
参照数のインクリメント、デクリメント
コピーコンストラクタで参照数をインクリメント、デストラクタでデクリメントしましょう。
デクリメントの結果、0になっていればshared_ptrの参照先をdeleteし、参照カウンタもdeleteします。
template < typename T > class shared_ptr { public: ...略 shared_ptr( shared_ptr const& p ) : ptr( p.ptr ) , count( p.count ) { if( count ) ++ ( *count ); } ~shared_ptr() { if( count ) { if( --( *count ) == 0 ) { delete ptr; delete count; } } } ...略 };
動作結果を確認してみましょう。
{ shared_ptr< int > a( new int( 100 ) ); //参照カウンタ=1 { shared_ptr< int > b = a; //参照カウンタ=2 } //参照カウンタ=1 } //参照カウンタ=0
問題ないですね。
operator=
以下のように既存のshared_ptrにもコピーできるようにoperator=も追加しましょう。
shared_ptr< int > a( new int( 100 ) ); shared_ptr< int > b; b = a;
参照カウンタの制御用にaddref()、reelase()を追加
template < typename T > class shared_ptr { public: ...略 shared_ptr( shared_ptr const& p ) : ptr( p.ptr ) , count( p.count ) { addref(); } ~shared_ptr() { release(); } shared_ptr& operator=( shared_ptr const& p ) { if( this != &p ) { //現在の参照先をreleaseしてからコピー、インクリメント release(); ptr = p.ptr; count = p.count; addref(); } return *this; } void addref() { if( count ) ++ ( *count ); } void release() { if( count ) { if( --( *count ) == 0 ) { delete ptr; delete count; } } } ...略 };
以上で単純なコピーが可能になりました。
ここまでの内容をboostのshared_ptrtと比べてみると、、、全然違いますね^^
次回はshared_countを追加してみましょう。