Handle类与智能指针
2014-09-18 本文已影响330人
eesly_yuan
Handle类与智能指针的用途或者说是设计它的目的是,能够让我不必去复制对象,同时能够达到运行时绑定对象的方法
今天在前面看到了智能指针的定义及用途,后面又看到了handle类,很好奇,这二者有什么区别,于是各种google,大致得出下面的结论(仅供参考)
智能指针主要目的在于使用RAII管理资源,实现资源的自动释放。
句柄类也实现了智能指针的功能,但是其主要目的是为了在数组中实现多态。
handle类行为类似指针,复制handle对象不会复制其基础对象,复制之后,两个handle指向同一个基础对象。创建一个handle对象,用户需要传递属于有handle管理类型的动态分配对象的地址,从此刻起,handle将拥有这个对象,并且一旦不在有handle对象与该对象关联,handle类负责删除该对象。这个与指针很像,可以说二者基本一致,只是在用的领域有一些不同。
智能指针或者说Handle有三种写法
- 1、写一个类specialClass,这个类包含需要管理成员指针和引用计数,然后定义一个handle类其中只有一个成员specialClass*管理我们刚刚那个类如下所示
//all member is private..only assess by Handle
class UPoint
{
friend class Handle;
Point p;
int u;//count
UPoint():u(0){}
UPoint(const Point&pv):p(pv){}
UPoint(int x,int y):p(x,y),u(1){}
UPoint(const UPoint &up):p(up.p),u(1){}
};
//handle类管理
class Handle
{
public:
Handle():up(new UPoint){}
Handle(int x,int y):up(new UPoint(x,y)){}
Handle(const Point&p):up(new UPoint(p)){}
Handle(const Handle &h);
~Handle();
Handle& operator=(const Handle &h);
int x() const{ return up->p.x(); }
int y() const{ return up->p.y(); }
Handle& x(int);
Handle& y(int);
private:
UPoint *up;
void allocup();
};
- 2、可以看到第一种方法,计数是由UPoint来实现的,由Handle来管理。但做为编写者的我们肯定是不愿意这么写的.这意味着每写一个Handle都得写一个这样的Uxxxx.实在是费事。因此,我们可以很直观的想到一个写法,即在Handle里面指向的是Point *p和int *count;,有一个类似的例子如下
#ifndef MYHANDLE
#define MYHANDLE
template<typename T>
class Handle
{
public:
//默认构造函数
Handle(T *p = 0):ptr(p),use(new size_t(1)){}
//复制构造函数
Handle(const Handle & rhs):ptr(rhs.ptr),use(rhs.use){(*use)++;}
//赋值函数
Handle & operator=(const Handle & rhs)
{
*(rhs.use)++;
removeRef();
ptr = rhs.ptr;
use = rhs.use;
return *this;
}
//析构函数
~Handle(){removeRef();}
//指针解引用和箭头操作符,两个版本
T& operator*();
T* operator->();
const T& operator*() const;
const T* operator->() const;
private:
T * ptr;
size_t * use;
void removeRef()
{
if (--(*use) == 0)
{
delete ptr;
delete use;
}
}
};
- 3、上述这种方法是一个很好的解决方式,但还有一种方式是定义一个引用计数类,专门用于管理引用计数,让handle管理指针的行为,如下例子
#ifndef MYUC
#define MYUC
class UseCount
{
public:
//默认构造函数
UseCount():count(new size_t(1)){}
//复制构造函数
UseCount(const UseCount& uc):count(uc.count){ ++*count;}
//赋值操作符
UseCount& operator=(const UseCount &u){
reattach(u);
return *this;
}
//析构函数
~UseCount(){
if (--*count == 0)
delete count;
}
bool isonly() { return *count == 1;}//判断是否只指向一个计数,用于判断是否要删除
bool reattach(const UseCount &u);//重新连接,用于复制
bool makeonly();//分配一个新的,用于写时复制技术
private:
size_t *count;//计数
};
//用于定义赋值操作的时候使用
bool UseCount::reattach(const UseCount &u)
{
++*u.count;
if (-- *count == 0)
{
delete count;
count = u.count;
return true;
}
count = u.count;
return false;
}
bool UseCount::makeonly()//用于写时复制
{
if (*count == 1)
return false;
--*count;
count = new size_t(1);
return true;
}
//handle 管理类
template<typename T>
class HandleC
{
public:
//默认构造函数
HandleC(T *q = 0):p(q){};
//复制构造函数
HandleC(const HandleC &h):p(h.p),count(h.count){};//复制构造函数也很简单.其实可以省略,也不会出错
//赋值操作符
HandleC& operator=(const HandleC &rhs);
//析构函数,先析构这个析构函数内的内容,在析构类的成员
~HandleC(){if(count.isonly()) delete p;}
//解引用和->操作符
T * operator->();
T & operator*();
private:
T *p;//被Handle的对象
UseCount count;//使用UseCount
};
template<typename T> HandleC<T>& HandleC<T>::operator =(const HandleC<T> &rhs)
{
if (count.reattch(rhs.count))
delete p;
p = rhs.p;
return *this;
}
template<typename T> T*HandleC<T>::operator->()
{
if (p) return p;
throw std::runtime_error("access through unbound Handle");
}
template<typename T> T&HandleC<T>::operator*()
{
if (p) return *p;
throw std::runtime_error("dereference of unbound Handle");
}
#endif