smart_this(2)

最初に考えたのは、こんなプログラムだった。

template< class T >
class smart_this{
public:
    smart_ptr< T > getThis(){ return _this; }
    
    void* operator new( size_t size ){
        T* p = (T*)::malloc( size );
        p->setThis( smart_ptr< T >( p ) );
        return p;
    }
    void operator delete( void* ptr ){
        ::free( ptr );
    }
private:
    void setThis( smart_ptr< T > this_ ){
        _this = this_;
        _this->dec_ref();  // 参照カウンタをデクリメントする
    }
    
    smart_ptr< T > _this;
};

メモリを確保する段階で生成してやろうという考えだ。
参照カウンタをデクリメントしているのは、自身が参照しているといつまで経っても解放されなくなってしまうから。


で、これを継承して、

class Hoge : public smart_this< Hoge >{
};

こうやって使う。


しかし、これは大量のバグがある。


まず、operator newだと、

Hoge hoge;

とかローカルで作ると、スマートポインタのセットできない。


次に、

_this = this_

この部分で、_this が初期化されていないこと。
通常スマートポインタの代入演算子は、参照カウンタオブジェクトをデクリメントしてから、新しいポインタをセットすると思うのだけれども、コンストラクタが呼ばれていないため、その参照カウンタオブジェクトが生成されていない。
よって間違いなくアクセス違反で落ちる。


まだ問題はある。
実はこれ、operator new を抜けた時点で、Hoge が解放される。
参照数を数えてみると、setThis()の引数で作ったので1、setThis()に渡すためにコピーしたから2、_this にコピーして3、このときアクセス違反になるけど今は気にしない。で、デクリメントして2、関数を抜けて this_ を解放するから1、そして operator new を抜けて0。見事解放されます。
しかも delete で。
しかもこのあとコンストラクタを呼び出そうとするので、大体はアクセス違反。もし起こさなかったとしてもどっかで落ちる。


最後。これ、コンパイル通らない

p->setThis( smart_ptr< T >( p ) );

privateメソッドを呼び出しているからです。
テンプレートクラスの operator new に対する friend 指定のやりかたなんて知りませんがな(;´Д`)
ちなみに、

friend void* smart_this< T >::operator new( size_t );

これだと無理でしたorz



まあつまりこのクラスは、却下も却下、大却下です。


さて、次の案を考えてみますか。