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もこういった感じの処理になってるとは思うのですが。