您的位置:首页 > 其它

智能指针的一种实现

2014-09-13 19:09 330 查看
下面是实现智能指针的一种方式,原理就是实现并自动处理引用计数操作的C++模板。

#ifndef SMARTPTR_H
#define SMARTPTR_H

template <class T> class SmartPtr;

////////////////////////////////////////////////////////////////
// IRefCount
// 是引用计数的接口
// 类应该自己实现它
// 或者 SmartPtr 会提供它的 IRefCount 的内部实现
template <class T> class IRefCount
{
friend class SmartPtr<T>;
protected:
virtual void AddRef() = 0;
virtual void Release() = 0;
virtual T * GetPtr() const = 0;
};

////////////////////////////////////////////////////////////////
// IRefCountImpl
// 是 IRefCount 的标准实现
// 要使用的话直接从其派生,比如
// class CMyObject : public IRefCountImpl<CMyObject> { ... }
// 注意:实现 IRefCount 是可选的,但这么做可以减少内存碎片
template <class T> class IRefCountImpl
: public IRefCount<T>
{
private:
int m_Count;
protected:
virtual void AddRef() { m_Count++; }
virtual void Release()
{
assert(m_Count >= 0);
m_Count--;
if(m_Count <= 0)
{
Destroy();
}
}
virtual T * GetPtr() const { return ((T *)this); }
virtual void Destroy()
{
if(GetPtr() != NULL)
delete GetPtr();
}

IRefCountImpl() { m_Count = 0; }
};

////////////////////////////////////////////////////////////////
// SmartPtr
template <class T> class SmartPtr
{
private:
IRefCount<T> * m_RefCount;

////////////////////////////////////////////////////////////
// RefCounter
// 为没有实现 IRefCount 的类提供内部实现
// SmartPtr会自动选择内部实现或者实现 IRefCount 的类
class RefCounter : public IRefCountImpl<T>
{
private:
T * m_Ptr;
protected:
virtual T * GetPtr() const { return m_Ptr; }
virtual void Destroy() { delete this; }
public:
RefCounter (T * ptr) { m_Ptr = ptr; }
virtual ~RefCounter() { IRefCountImpl<T>::Destroy(); }
};

// 如果T没有实现IRefCount,这个方法会被调用
void Assign(void * ptr)
{
if(ptr == NULL)
Assign((IRefCount<T> *)NULL);
else
{
Assign(new RefCounter(static_cast<T *>(ptr)));
}
}

// 如果T实现了 IRefCount,这个方法会代替Assign(void * ptr)
// 这使得一些内存使用优化
void Assign(IRefCount<T> * refcount)
{
if(refcount != NULL)
refcount->AddRef();
IRefCount<T> * oldref = m_RefCount;
m_RefCount = refcount;
if(oldref != NULL)
oldref->Release();
}
public:
SmartPtr() { m_RefCount = NULL; }
SmartPtr(T * ptr) { m_RefCount = NULL; Assign(ptr); }
SmartPtr(const SmartPtr & sp) { m_RefCount = NULL; Assign(sp.m_RefCount); }
virtual ~SmartPtr() { Assign((IRefCount<T> *)NULL); }

T * GetPtr() const { return (m_RefCount == NULL) ? NULL : m_RefCount->GetPtr(); }

// 赋值操作符
SmartPtr& operator = (const SmartPtr & sp)
{
Assign(sp.m_RefCount);
return * this;
}
SmartPtr& operator = (T * ptr)
{
Assign(ptr);
return * this;
}

// T访问和const转换
T * operator ->()
{
assert(GetPtr() != NULL);
return GetPtr();
}
operator T* () const { return GetPtr(); }

// 工具
bool operator !()
{
return GetPtr() == NULL;
}
bool operator ==(const SmartPtr &sp)
{
return GetPtr() == sp.GetPtr();
}
bool operator !=(const SmartPtr &sp)
{
return GetPtr() != sp.GetPtr();
}
};
#endif

下面是使用这个模板的例子:
////////////////////////////////////////////////////////////////
// SmartPtr.cpp
// 如何使用 SmartPtr 的例子
#include <stdio.h>
#include <assert.h>
#include "smartptr.h"

// 定义一个自己的类用来测试
class CMyObject
{
char *name;
public:
CMyObject(char *aname)
{
name = aname;
printf("create %s\n", name);
}
virtual ~CMyObject()
{
printf("delete %s\n", name);
}
void print()
{
printf("print %s\n", name);
}
};

// 测试作为返回值使用
SmartPtr<CMyObject> f1(char *name)
{
return SmartPtr<CMyObject>(new CMyObject(name));
}

// 测试作为参数使用
void f2(CMyObject *o)
{
printf("(print from a function)");
o->print();
}

int main()
{
SmartPtr<CMyObject> ptr1(new CMyObject("1")); // 创建对象“1”
SmartPtr<CMyObject> ptr2 = new CMyObject("2"); // 创建对象“2”

ptr1 = ptr2; // 销毁对象“1”
ptr2 = f1("3"); // 作为返回值使用
ptr2 = NULL; // 销毁对象“3”

/* 错误的用法
CMyObject o1;
ptr1 = &o1; // 不能这么赋值,因为 o1 在栈上

CMyObject * o2 = new CMyObject;
ptr1 = o2;
ptr2 = o2; // 不能这么做,除非CMyObject实现了IRefCount接口
*/
// 甚至可以在整数上用 SmartPtr
SmartPtr<int> a(new int);
SmartPtr<int> b(new int);

*a = 5;
*b = 6;

// 没有内存泄漏!!!
return 0;
}只要SmartPtr对象在作用域内,而且避免那些错误用例,就不会造成内存泄漏。然而,智能指针并不是在每种情况下都能使用的。一个局限就是它不能在多线程的环境下使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: