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();