2年・3年向けの内容です。
main()
{
int *p=new int;
}
newで確保しただけでプログラムが終わってしまいメモリを解放していません。(メモリリーク)
main()
{
int *p=new int;
delete p;
}
これで正しく解放されました。
deleteするのを忘れやすいし、どこかでnewしたポインタを他のプレイヤーが参照してたりして、
参照しているのに他でdeleteすると参照先が見つからなくてエラーが出て落ちたり・・
ダウンジングポインタ=ポインタの参照先が見つからねえ!
(こっちはプログラム落ちます)
メモリーリーク =解放し忘れてる!
これらの問題をあるひとつのフォーマットにしたがって書くことで、改善できます。
それが今回紹介する
スマートポインタです。
[0回]
main()
{
smart_ptr<int> p(new int); // int* p=new int とほぼ同義
}
これでリークはしません。
自分で構造体を作ってみます。
struct MyCls
{
MyCls(){puts("コンストラクタ\n")}
~MyCls(){puts("デストラクタ\n")}
};
main()
{
smart_ptr<MyCls> p(new MyCls); // int* p=new int とほぼ同義
}
正しく呼ばれます。
スマートポインタのクラスを超簡単に書くと、(このクラスは例なので利用できません。)
template<class Type>
class smart_ptr
{
public:
Type* operator->(){retrun pObject}
void operator=( Type& _obj ){ *use_cnt+=1; pObject=_obj.pObject; use_cnt=_obj.use_cnt } // = 演算子
~smart_ptr(){ *use_cnt-=1; if( *use_cnt==0 ){ delete pObject;} } // デストラクタ
int* use_cnt; // 所有カウント
Type* pObject; // 所有先の物
}
スマートポインタには
参照するポインタと
所有カウンタを持っています。
スマートポインタ同士がコピーされると所有カウンタが1増えます。
逆に参照されなくなると(smart_ptrクラスのデストラクタが呼ばれると)
所有カウンタが1減ります。
1減らして 所有カウンタが0になったらポインタの解放を行います。
スマートポインタを使うとダウンジングポインタやメモリリークはなくなります。
注:参照カウンタ0の時にメンバにアクセスしようとしたらpx!=0とエラーボックスが出て落ちます。
使いすぎはダメです。
VisualStadio2010の人はsmart_ptrクラスが標準ライブラリで実装されています
<memory>をインクルードして std::shared_ptr<Type> のようにして使うこともできます。
boostにもあって、boost:shared_ptr<Type>のようにして書きます。
あと、私の説明よりこっちの説明が
神がかっているのでこちらをオススメします。
http://www.ustream.tv/recorded/2981654
スマートポインタを知っている人でも必見です。詳しく振るまいを知ることができます!
番外編
shared_ptr<void> とデリータを設定することでガーベジコレクション的なのも作れます。
std::list<void *> m_lisなどのリストで破棄時にこのリストに登録しておいて、
いらなくなったら、解放 みたいなことができればいいのですが、deleteしても、
型情報がvoid*になっているためデストラクタが正しく呼ばれません。
デリータに以下のリストに登録するようにしておく
std::list< shared_ptr<void> > m_lis; だとclearするだけでデストラクタを呼ぶことができます。
なぜかと言うと・・・この動画を見て下さい☆
リーダ和田
PR
COMMENT