GoogleのC++スマートポインタ実現

10308 ワード

//                   
class
RefCountedBase { public: virtual int AddRef()=0; virtual int Release()=0; protected: virtual ~RefCountedBase(){} };

インテリジェントポインタオブジェクトクラスの実装
template <class T>

class RefCountedPtr

{

public:

    RefCountedPtr() : m_ptr(NULL)

    {

    }



    RefCountedPtr(T* p) : m_ptr(p) 

    {

        if (m_ptr)m_ptr->AddRef();

    }



    RefCountedPtr(const RefCountedPtr<T>& r) : m_ptr(r.m_ptr) 

    {

        if (m_ptr)m_ptr->AddRef();

    }



    template <typename U>

    RefCountedPtr(const RefCountedPtr<U>& r) : m_ptr(r.get())

    {

        if (m_ptr) m_ptr->AddRef();

    }



    ~RefCountedPtr()

    {

        if (m_ptr) m_ptr->Release();

    }



    T* get() const { return m_ptr; }

    operator T*() const { return m_ptr; }

    T* operator->() const { return m_ptr; }





    T* release() 

    {

        T* retVal = m_ptr;

        m_ptr = NULL;

        return retVal;

    }



    RefCountedPtr<T>& operator=(T* p) 

    {

        // AddRef first so that self assignment should work

        if (p) p->AddRef();

        if (m_ptr) m_ptr ->Release();

        m_ptr = p;

        return *this;

    }



    RefCountedPtr<T>& operator=(const RefCountedPtr<T>& r)

    {

        return *this = r.m_ptr;

    }



    template <typename U>

    RefCountedPtr<T>& operator=(const RefCountedPtr<U>& r)

    {

        return *this = r.get();

    }



    void swap(T** pp)

    {

        T* p = m_ptr;

        m_ptr = *pp;

        *pp = p;

    }



    void swap(RefCountedPtr<T>& r)

    {

        swap(&r.m_ptr);

    }



protected:

    T* m_ptr;

};

 
使用例は次のとおりです.
class MyClass:public RefCountedBase

{

public:

       ...



       virtual int AddRef() 

    {

        return ++m_count;

    }



    virtual int Release() 

    {

        int count = --m_count;

        if (!count) 

        {

            delete this;

        }

        return count;

    }



private:

     

  int m_count;

};



RefCountedPtr<MyClass> test=new RefCountedObject<MyClass>()

C++テンプレートを使用すると、オブジェクトを作成するたびにAddRef()およびRelease()インタフェースを実装する手間を省くことができます.
template <class T>

class RefCountedObject : public T 

{

public:

    RefCountedObject() : m_count(0) 

    {

    }



    template<typename P>

    explicit RefCountedObject(P p) : T(p), m_count(0) 

    {

    }



    template<typename P1, typename P2>

    RefCountedObject(P1 p1, P2 p2) : T(p1, p2), m_count(0) 

    {

    }



    template<typename P1, typename P2, typename P3>

    RefCountedObject(P1 p1, P2 p2, P3 p3) : T(p1, p2, p3), m_count(0) 

    {

    }



    template<typename P1, typename P2, typename P3, typename P4>

    RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4)

        : T(p1, p2, p3, p4), m_count(0) 

    {

    }



    template<typename P1, typename P2, typename P3, typename P4, typename P5>

    RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)

        : T(p1, p2, p3, p4, p5), m_count(0) 

    {

    }



    virtual int AddRef() 

    {

        return AtomicOps::Increment(&m_count);

    }



    virtual int Release() 

    {

        int count = AtomicOps::Decrement(&m_count);

        if (!count) 

        {

            delete this;

        }

        return count;

    }



protected:

    virtual ~RefCountedObject() {

    }



    int m_count;

};

使用方法は次のとおりです.
class Test:public RefCountedBase

{

public:

    void test(){}

};



//AddRef() Release()       ,     

RefCountedPtr<Test> test=new RefCountedObject<Test>()

test->test();