RAII( resource acquisition is initialization ),所谓初始化即资源获取,它认为一个资源应该利用对象管理设施来管理,也就是说,你需要一个资源,你用一个对象的构造函数来获得它,用析构函数来释放它.
智能指针技术,是这一思想的完美体现,它即可以像内建指针(即你new得的对象地址指针)那样操纵对象,又可以跟踪与控制资源的生命期.
为智能指针添加引用记数,则是为了让它可以到处传递,因为智能指针实际上是一个对象,如果你直接浅拷贝构造,那么在原来对象销毁时,拷贝得的对象所包含的资源实际上已经不存在了,而如果深拷贝,那么效率又是很低下的,因为你需要为了新的拷贝对象新建整个资源.所以,我们让初试对象以及其他所有的拷贝都实际指向同一个资源的地址,然后用一个引用记数来跟踪对象个数,第一个对象负责申请资源,最后一个对象负责清理资源.
下面,我们来逐一分析:
(1)共同的资源
struct counter {
counter(X* p = 0, unsigned c = 1) : ptr(p), count(c) {}
X* ptr;
unsigned count;
}* itsCounter;
这个struct是一个二元组,它包含了资源指针与引用记数,而以后,初始智能指针以及所有它的拷贝都实际上只保存一个这样的结构内容.
(2)资源的获取与归还
void Acquire(counter* c) throw()
{ // increment the count
itsCounter = c;
if (c) ++c->count;
}
virtual void Release()
{ // decrement the count, delete if it is 0
if (itsCounter) {
if (--itsCounter->count == 0) {
delete itsCounter->ptr;
delete itsCounter;
}
itsCounter = 0;
}
}
以上两个函数显示每个新的拷贝对象,资源的获取,实际上只是获取看见资源的能力以及对于资源引用对象数的增加,
而资源的释放,只让最后一个对象完成实际工作,其他只是简单的告诉资源多了一个人关注它.
(3)智能指针的拷贝与析构
explicit CRefCountPtr(X* p = NULL) // allocate a new counter
: itsCounter(NULL) {if (p) itsCounter = new counter(p);}
virtual ~CRefCountPtr()
{Release();}
CRefCountPtr(const CRefCountPtr& r) throw()
{Acquire(r.itsCounter);}
CRefCountPtr& operator=(const CRefCountPtr& r)
{
if (this != &r) {
Release();
Acquire(r.itsCounter);
}
return *this;
}
这里实际上就是简单的利用上面的概念来完善
(4)模拟内建指针
X& operator*() const throw() {return *itsCounter->ptr;}
X* operator->() const throw() {return itsCounter->ptr;}
不再赘述
(5)总的代码(利用模板技术)
#ifndef REFCOUNTPTR_H
#define REFCOUNTPTR_H
template <class X> class CRefCountPtr
{
public:
typedef X element_type;
explicit CRefCountPtr(X* p = NULL) // allocate a new counter
: itsCounter(NULL) {if (p) itsCounter = new counter(p);}
virtual ~CRefCountPtr()
{Release();}
CRefCountPtr(const CRefCountPtr& r) throw()
{Acquire(r.itsCounter);}
CRefCountPtr& operator=(const CRefCountPtr& r)
{
if (this != &r) {
Release();
Acquire(r.itsCounter);
}
return *this;
}
X& operator*() const throw() {return *itsCounter->ptr;}
X* operator->() const throw() {return itsCounter->ptr;}
X* Get() const throw() {return itsCounter ? itsCounter->ptr : 0;}
bool Unique() const throw()
{return (itsCounter ? itsCounter->count == 1 : true);}
bool Valid() const throw() { return(itsCounter != 0); }
protected:
struct counter {
counter(X* p = 0, unsigned c = 1) : ptr(p), count(c) {}
X* ptr;
unsigned count;
}* itsCounter;
void Acquire(counter* c) throw()
{ // increment the count
itsCounter = c;
if (c) ++c->count;
}
virtual void Release()
{ // decrement the count, delete if it is 0
if (itsCounter) {
if (--itsCounter->count == 0) {
delete itsCounter->ptr;
delete itsCounter;
}
itsCounter = 0;
}
}
};
#endif // RefCountPtr_H