スマートポインタの第二幕です(`・ω・´)
なぜケイン・コスギかというと、僕の中で一番好きなコスギが ケイン・コスギ だからです。
『べつにケイン・コスギはスマートじゃない』っていうのは受け付けません。
取り敢えず 前回のスマートポインタ に付け加えたい、無くてはならない機能としては,,,,
************************************
・スマートポインタ間のコピー
・アップキャストの対応
************************************
が最低限でしょうか。
スマートポインタ間のコピーは、
SmartPtr< MyClass > spMyClassB;
spMyClassB = spMyClassA;
================================================
保持しているポインタの受け渡しと参照カウンタの共有化をさせる。
================================================
ということです。
これは Operator 機能を使えば出来そうです。
********【 Operator 】*********
クラスに
void opeartor = ( /* 引数 */ )
{
}
と書けば 『= 関数を作成した』みたいな感じです。
だから関数の中身に自分で好きな記述をすることができます。
使い方としては
{
public:
void operator = ( Object* pObj )
{
printf( "= 関数が呼ばれたよ。" );
}
};
~~~~~~~~~~~
Object* pObjectA = new Object;
Object* pObjectB = new Object;
pObjectB = pObjectA;
----【出力】----
"= 関数が呼ばれたよ。"
という感じで、 = の右側に書いた物が引数となります。
べつに Object型のポインタを引数に取らなくても...
{
public:
void operator = ( int value )
{
printf( "数字は %d です¥n", &value );
}
};
~~~~~~~~~~~
Object* pObjectA = new Object;
pObjectA = 1;
pObjectA = 3;
----【出力】----
"数字は 1 です"
"数字は 3 です"
と、引数はなんでもいいです。
取り敢えず ”演算子を継承する” と僕は覚えてます。
コレは "==", "+", "-", "->", "/", "*". "<<" など
c++ にある演算子は全部継承できます。
****************************
スマートポインタ間のコピーが出来るように operator = をスマートポインタクラスに記述...
すでに 自分が ポインタを保持している可能性が あるので、まず Release をすることが必須です。
それから入れ替えます。
そして、ポインタを共有する人数が増えたので参照カウンタを増加。。。
こんなかんじで実行。
良い感じ・・・
便利に使いやすくするように operator -> と operator * も記述。。。
-> と * で
保持してあるポインタにアクセスできるようになりました!(`・ω・´)
これで使いやすさ UP ↑
*************************
次に 【 アップキャスト 】
class A
{};
class B : public A
{};
~~~~~~~~~~~~~
SmartPtr< A > A( new B );
や
SmartPtr< A > A;
SmartPtr< B > B( new B );
A = B;
を実現したい。
先ほどのスマートポインタクラスではエラーとなるので
新たな コピーコンストラクタ と operator を作成。
template< class T >
class SmartPtr
{
protected:
/* 内包されるポインタ */
T* mPtr;
/* 参照カウント */
unsigned int* mpCount;
public:
explicit SmartPtr( T* ptr = NULL )
: mPtr( ptr ), mpCount( NULL )
{
if ( mPtr )
{
mpCount = new unsigned int( 1 );
}
}
explicit SmartPtr( SmartPtr< T >& sp )
{
mPtr = sp.mPtr;
mpCount = sp.mpCount;
( *mpCount )++;
}
/**
* アップキャスト対応させるコンストラクタ
*/
template< class T2 >
SmartPtr( const SmartPtr< T2 >& sp )
{
mPtr = sp.GetPtr();
mpCount = sp.GetCounter();
++*mpCount;
}
~SmartPtr()
{
Release();
}
/**
* 内包してあるポインタを渡す
*/
T* GetPtr() const { return mPtr; }
T* operator -> () const { return GetPtr(); }
T& operator * () const { return *GetPtr(); }
// 参照カウンタ
unsigned int* GetCounter() const { return mpCount; }
/**
* [ Operator = ]
* スマートポインタ間のコピー
*/
SmartPtr< T >& operator = ( const SmartPtr< T >& sp )
{
if ( mPtr != sp.GetPtr() )
{
Release();
mpCount = sp.mpCount;
mPtr = sp.mPtr;
if ( mpCount != NULL )
++*mpCount;
}
return *this;
}
// アップキャスト対応
template< class T2 >
SmartPtr< T >& operator = ( const SmartPtr< T2 >& sp )
{
if ( mPtr != sp.GetPtr() )
{
Release();
mpCount = sp.GetCounter();
mPtr = sp.GetPtr();
if ( mpCount != NULL )
++*mpCount;
}
return *this;
}
protected:
void Release()
{
//** 参照カウンタが0になったらdeleteを行う。
if ( mPtr && --*mpCount == 0 )
{
delete mPtr;
delete mpCount;
mPtr = NULL;
mpCount = NULL;
}
}
};
template< class T2 >
SmartPtr( const SmartPtr< T2 >& sp )
template< class T2 >
SmartPtr< T >& operator = ( const SmartPtr< T2 >& sp )
これが、アップキャストに対応させたコピーコンストラクタと operator = です。
template はビルド通した時に
『おい! この記述は出来ねーぞks!!!』
と罵倒してくれるので、
実行前にエラーを出してくれます。
すごい・・・便利です・・・///
使ってみた ↓
【 コピーコンストラクタ 】
【 operator = 】
うまくビルドも通ってメモリリークも発生していません!
(゚∀゚≡(゚∀゚≡゚∀゚)≡゚∀゚)
コレを元に自分で機能を追加していってみるといいんじゃないかと思います。
いじょu!
****************************************
【 (URL) スマートポインタ02 】
****************************************
『iPhone開発の XCode とかは自力でメモリ管理してくれてるからいいなぁ・・・』
と思ってたりもするけどメモリ関係は自分で管理してないと不安で仕方がないと感じる自分もいるので iPhone開発中、実はXCodeのメモリ管理を切ってたりします。
というか、
ちょっと前にやっとObjective-Cをそこそこ使えるようになって、Objective-Cのみでゲーム作ったりした。
それまで C++ で書いてました。
Objective-C 使いやすいとは思うけど独特のメモリ管理がムズムズする。
あと 実機ではOpenGL ES で使えない機能があったりしてめっちゃ困る。
前モデルを3Dで出すアプリ作ってた時、テクスチャに行列書き込みが出来なかった・・
あと、シュミレーターではアンチエイリアス効く所が実機では効かなかった・・・
あ、愚痴になってきたのでココらへんで去ります