智能指针的一种实现
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对象在作用域内,而且避免那些错误用例,就不会造成内存泄漏。然而,智能指针并不是在每种情况下都能使用的。一个局限就是它不能在多线程的环境下使用。
#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对象在作用域内,而且避免那些错误用例,就不会造成内存泄漏。然而,智能指针并不是在每种情况下都能使用的。一个局限就是它不能在多线程的环境下使用。
相关文章推荐
- 智能指针的一种实现
- c++ 智能指针的一种实现方法
- 一种基于引用计数的智能指针的实现
- C++一种智能指针的实现
- (转)智能指针的另外一种实现 - Smart pointers in Delphi
- 一种基于引用计数机制的智能指针实现
- c++ 一种智能指针的实现
- 一种基于引用计数机制的智能指针实现
- 一种智能指针的实现方式
- (转)智能指针的另外一种实现 - Smart pointers in Delphi
- (改进)Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现(二)
- 实现一个简单的智能指针
- 最简单的智能指针实现方法
- 请谈谈什么是智能指针,com实现的原理 zz
- c++中的智能指针实现
- C++标准库中简单智能指针auto_ptr的模仿实现源码
- 有效的使用和设计COM智能指针——条款3:按照功能和实现原理选择合适的智能指针
- 智能指针的类实现
- 网络编程资料总结(四)----一种基于UDP协议实现P2P智能穿越NAT的方案
- 智能指针 安全引用的实现