DirectX用のスマートポインタの作成
DirectX関連のオブジェクトを使用する場合に便利なスマートポインタを自作しました。
// -- smart_ptr.h -- #include <memory> namespace ddp { template<class T> class com_ptr { private: T* m_pComObj; public: explicit com_ptr (T* comObj = NULL) { m_pComObj = comObj; } // コピーコンストラクタ com_ptr(const com_ptr<T>& comObj) { // コピーコンストラクタの場合はAddRef呼ぶだけ m_pComObj = comObj.m_pComObj; if ( m_pComObj ) { m_pComObj->AddRef(); } } // 代入処理 com_ptr<T>& operator=(const com_ptr<T>& comObj) { // 現在所有しているポインタはReleaseで解放 if ( m_pComObj ) { m_pComObj->Release(); } // ポインタのコピー m_pComObj = comObj.m_pComObj; // コピーが発生したのでAddRefする if ( m_pComObj ) { m_pComObj->AddRef(); } return *this; } // DirectXの生成系関数にポインタを渡すときに使用する T** creator_ptr () { // 生成時にAddRefされるので予めReleaseで参照カウンタを減らしておく if ( m_pComObj ) { m_pComObj->Release(); } return &m_pComObj; } // 保持しているポインタを透過的に扱えるようにする T* operator->() { return m_pComObj; } // ポインタを保持しているかどうかをチェックする operator bool () { return (m_pComObj != NULL); } ~com_ptr () { if ( m_pComObj ) { m_pComObj->Release(); } } }; // shared_ptrを取り込む using std::tr1::shared_ptr; };
ddp::com_ptrという名前です。このddpという名前空間はとりあえず自分用ライブラリということで。
また、普通のオブジェクト用にshared_ptrを自作しようと思ったんですが、これはわざわざ作らなくてもTR1に既に存在しているのでusingでddpに取り込むだけにしました。
以下動作確認の例です。
#include <iostream> #include "smart_ptr.h" using std::cout; using std::endl; class CSample { private: int m_refCount; public: CSample () { m_refCount = 1; cout << this << " Create : " << m_refCount << endl; } void AddRef () { m_refCount++; cout << this << " AddRef : " << m_refCount << endl; } void Release() { m_refCount--; cout << this << " Release : " << m_refCount << endl; } void output () { cout << "output" << endl; } }; void func (ddp::com_ptr<CSample>) { } int main () { ddp::com_ptr<CSample> obj1(new CSample); ddp::com_ptr<CSample> obj2 = obj1; ddp::com_ptr<CSample> obj3; obj3 = obj1; func(obj1); func(obj2); func(obj3); obj3 = ddp::com_ptr<CSample>(new CSample); func(ddp::com_ptr<CSample>(new CSample)); obj3->output(); return 0; }
$ main 00384FC8 Create : 1 00384FC8 AddRef : 2 00384FC8 AddRef : 3 00384FC8 AddRef : 4 00384FC8 Release : 3 00384FC8 AddRef : 4 00384FC8 Release : 3 00384FC8 AddRef : 4 00384FC8 Release : 3 00382E90 Create : 1 00384FC8 Release : 2 00382E90 AddRef : 2 00382E90 Release : 1 00382EA0 Create : 1 00382EA0 Release : 0 output 00382E90 Release : 0 00384FC8 Release : 1 00384FC8 Release : 0
うまくいってるっぽいです。ちゃんと最後には参照カウンタが0になっています。