std::auto_ptrを自作する
前回勉強したstd::auto_ptrですが、とても興味深い内容だったので自作してみました。
myauto_ptrクラスです。
#include <iostream> #include <memory> using std::cout; using std::endl; template<class T> class myauto_ptr { public: myauto_ptr(T* p) { m_p = p; } myauto_ptr (const myauto_ptr<T>& obj) { // 果たしてこの実装は良いのかどうか? *this = const_cast<myauto_ptr<T>&>(obj); } myauto_ptr<T>& operator=(myauto_ptr<T>& obj) { this->m_p = obj.m_p; obj.m_p = NULL; return *this; } T* operator->() { return m_p; } ~myauto_ptr() { if ( m_p != NULL ) { cout << "~myauto_ptr => delete " <<endl; delete m_p; m_p = NULL; } else { cout << "~myauto_ptr " <<endl; } } private: T* m_p; }; class CSample { public: CSample(int num) { m_num = num; cout << "コンストラクタ" << endl; } ~CSample() { cout << "デストラクタ" << endl; } int getNum () { return m_num; } private: int m_num; }; myauto_ptr<CSample> create (int num) { myauto_ptr<CSample> p( new CSample(num) ); return p; } int main () { myauto_ptr<CSample> p = create(100); cout << p->getNum() << endl; return 0; }
$ main コンストラクタ ~myauto_ptr 100 ~myauto_ptr => delete デストラクタ
動作確認のため、myauto_ptrにはデバッグ文を入れてます。
create関数内でのp変数のデストラクタではCSampleをdeleteせずにちゃんとmain関数内でのp変数のデストラクタでCSampleのdeleteが行われていることが確認できますね。
実装するにあたって一つ気になったところがあります。
それはコピーコンストラクタの部分です。
myauto_ptr (const myauto_ptr<T>& obj) { // 果たしてこの実装は良いのかどうか? *this = const_cast<myauto_ptr<T>&>(obj); }
コピーコンストラクタを作るには必ずconstの参照型のコンストラクタを用意しなければなりません。
ですがそうすると、元のオブジェクトの値が書き換えられなくなるのでstd::auto_ptrの特徴である、ポインタの移動処理ができないのです。
なのでここでは無理やりconst_castでconstを除去しています。
果たして目的のためならこういったマナー違反も辞さない処理で問題ないのかちょっとわからないです。
でも多分これ以外に方法はないと思うので実際のstd::auto_ptrもこういった感じの処理になってるとは思うのですが。