<注意!>
以下は古い実装になりました。現在下記の実装についてサポートは終了しております。
最新の実装はツール編「スマートポインタ」をご覧下さい。
smart_ptrクラスの完全実装
以下から下をコピペすると直ぐに使えるようになります。
デバッグ時に「DEBUG_smp.txt」というテキストファイルを出力させるため#ifディレクティブなどが
ついております。見づらい点はご了承ください。
// smart_ptrクラス
// 動的に生成された変数の削除を管理し、実体への参照が無い時に消去する。
// smart_ptrクラスを通した実体への参照を保証する。
// デバッグ時には「DEBUG_smp.txt」というデバッグファイルを出力
template <class T>
class smart_ptr
{
private:
UINT *m_pRefCnt; // 参照カウンタへのポインタ
T* m_pPtr; // T型のオブジェクトのポインタ
private:
// 参照カウンタ増加
#if _DEBUG
void AddRef(char *coment="No Coment")
{
(*m_pRefCnt)++;
// 出力
ofstream ofs;
ofs.open("DEBUG_smp.txt", ios::app);
ofs << this << "\t" <<
m_pPtr << "\t[" << *m_pRefCnt << "]\t"
<< coment << endl;
ofs.close();
}
#else
void AddRef(){(*m_pRefCnt)++;}
#endif
// 参照カウンタを減少
#if _DEBUG
void Release(char *coment="No Coment")
#else
void Release()
#endif
{
#ifdef _DEBUG
ofstream ofs;
ofs.open("DEBUG_smp.txt", ios::app);
ofs << this << "\t" <<
m_pPtr << "\t[" << *m_pRefCnt-1 << "]\t"
<< coment << endl;
ofs.close();
#endif
if(--(*m_pRefCnt) == 0){
delete[] m_pPtr;
delete m_pRefCnt;
}
}
public:
// デフォルトコンストラクタ
explicit smart_ptr(T* src=NULL)
{
m_pRefCnt = new UINT;
*m_pRefCnt = 0;
m_pPtr = src;
#if _DEBUG
AddRef("デフォルトコンストラクタによりカウンタ増加");
#else
AddRef();
#endif
}
// コピーコンストラクタ
smart_ptr(const smart_ptr<T> &src)
{
// ポインタコピー
m_pRefCnt = src.m_pRefCnt;
m_pPtr = src.m_pPtr;
// 自分自身の参照カウンタを増加
#if _DEBUG
AddRef("コピーコンストラクタによりカウンタ増加");
#else
AddRef();
#endif
}
// デストラクタ
virtual ~smart_ptr()
{
#if _DEBUG
char c[100];
sprintf(c, "デストラクタで%08xの参照カウンタを減少\0",
m_pPtr);
Release(c);
#else
Release();
#endif
}
// =演算子のオーバーロード(明示的なコピー)
smart_ptr& operator =(const smart_ptr<T> &src)
{
// 自分自身への代入は不正で意味が無いので
// 行わない。
if(src.m_pPtr == m_pPtr)
return (*this);
// 自分の参照カウンタを1つ減少
#if _DEBUG
char c[100];
sprintf(c, "=演算子中で%08xの参照カウンタを減少\0",
m_pPtr);
Release(c);
#else
Release();
#endif
// ポインタコピー
m_pRefCnt = src.m_pRefCnt;
m_pPtr = src.m_pPtr;
// 自分自身の参照カウンタを増加
#if _DEBUG
sprintf(c, "=演算子中で%08xの参照カウンタを増加\0",
m_pPtr);
AddRef(c);
#else
AddRef();
#endif
return (*this);
}
// メンバ関数
// ポインタを移譲
void SetPtr(T* src = NULL)
{
// 参照カウンタを減らした後に再初期化
#if _DEBUG
char c[100];
sprintf(c, "SetPtr関数中で%08xの参照カウンタを減少\0",
m_pPtr);
Release(c);
#else
Release();
#endif
m_pRefCnt = new UINT;
*m_pRefCnt = 0;
m_pPtr = src;
#if _DEBUG
sprintf(c, "SetPtr関数中で%08xの参照カウンタを増加\0",
m_pPtr);
AddRef(c);
#else
AddRef();
#endif
}
// ポインタの貸し出し
T* GetPtr(){return m_pPtr;}
// 参照カウンタへのポインタを取得
UINT* GetRefPtr(){return m_pRefCnt;}
// アップキャスト
// ChildPtrはsmart_ptr::GetPtr関数で得られるポインタでなければエラー
// pRefCntはsmart_ptr::GetRefPtr関数で得られる参照カウンタへの
// ポインタでなければエラーになるので注意!
void Upcast(T* ChildPtr, UINT* pRefCnt)
{
// 引数のポインタが同じ場合は意味が無いのでキャストしない
if(ChildPtr == m_pPtr)
return;
// 引数のポインタと参照カウンタを受け継ぐ
#if _DEBUG
char c[100];
sprintf(c, "Upcast関数中で%08xの参照カウンタを減少\0",
m_pPtr);
Release(c);
#else
Release();
#endif
// ポインタコピー
m_pPtr = ChildPtr;
m_pRefCnt = pRefCnt;
// 参照カウンタを増加
#if _DEBUG
sprintf(c, "Upcase関数中で%08xの参照カウンタを増加\0",
m_pPtr);
AddRef(c);
#else
AddRef();
#endif
}
// ==比較演算子
BOOL operator ==(int val){
if(m_pPtr == val)
return TRUE;
return FALSE;
}
// !=比較演算子
BOOL operator !=(int val){
if(m_pPtr != val)
return TRUE;
return FALSE;
}
};