智能指针-复制构造
设计具有指针成员的类时,首先需要决定的是该指针应提供什么行为。例如将一个指针复制到另一个指针
时,两个指针指向同一个对象。当两个指针指向同一对象时,可能使用任一指针改变基础对象。类似地,很可
能一个指针删除了一对象时,另一指针的用户还认为基础对象仍然存在。
大多数C++类采用三种方法之一管理指针成员:
2.类采取值型行为。(复制指针同时,复制指针所指的空间,双份空间)
指针成员采取常规行为:
class HasPointer{
public:
HasPointer(int *p, int i): ptr(p), val(i) {}
public:
int * get_ptr() const { return ptr;}
int get_val() const { return val;}
void set_ptr( int * p) { ptr = p;}
void set_val( int i) { val = i;}
int get_ptr_val() const { return *ptr;}
void set_ptr_val( int i) { *ptr = i;}
private:
int *ptr;
int val;
};
指针成员常规行为客户端:
void main()
{
int *pObj = new int(20);
HasPointer ptr1(pObj,10);
/* 使用默认复制/赋值构造函数,即复制一个对象将复制它的成员 */
HasPointer ptr2(ptr1);
pObj?delete pObj:NULL;
ptr2.set_ptr_val(1);
/* objPtr1和objPtr2中的指针ptr指向相同的内存位置,且值相同
,这样处理会使得ptr具有普通指针的所有缺陷即无法避免垂悬指
针等,如以上的ptr2.set_ptr_val(1)就会很危险。
*/
}
类采取值型行为:
class HasPointer{
public:
HasPointer(const int &p, int i): ptr(new int(p)), val(i) {}
/* 复制构造将不再复制指针,它将分配一个新的int 对象,并初始化与被
复制对象相同的值,每个对象拥有自己的副本 */
HasPointer(const HasPointer &orig):ptr(new int(*orig.ptr)),val(orig.val){}
HasPointer& operator=(const HasPointer& hpo){
*ptr = *hpo.ptr;
val = hpo.val;
return *this;
}
~HasPointer(){delete ptr;}
public:
int * get_ptr() const { return ptr;}
int get_val() const { return val;}
void set_ptr( int * p) { ptr = p;}
void set_val( int i) { val = i;}
int get_ptr_val() const { return *ptr;}
void set_ptr_val( int i) { *ptr = i;}
private:
int *ptr;
int val;
}
// 相应的模板类
template< typename T>
class ValueHasPU{
public:
ValueHasPU(const T &ptemp, int val):pData(new T(ptemp)),iVal(val){}
ValueHasPU(const ValueHasPU & othor):pData(new T(*othor.pData)),iVal(othor.iVal){}
ValueHasPU& operator=(const ValueHasPU & rhs){
*pData = *rhs.pData;
iVal = rhs.iVal;
return *this;
};
~ValueHasPU(){ pData?delete pData:NULL;}
private:
T * pData;
int iVal;
};
智能指针方法: 定义智能指针的通用技术是,采用一个“使用计数”。
/*
定义一个单独的具体类用以封闭使用计数和相关指针,同时这个单独类中
成员均为私有的,只有其友元类的成员可以访问它的成员。
*/
class u_pointer{
friend class HasPointer;
u_pointer(int *p): ip(p), use(1) {}
~u_pointer() {ip?delete ip,ip=NULL:NULL;}
int * ip;
size_t use;
}
class HasPointer{
public:
HasPointer(int *p, int i): ptr(new u_pointer(p)), val(i) {}
HasPointer(const HasPointer &orig): ptr(orig.ptr), val(orig.val) { ptr->use++; }
HasPointer & operator= (const HasPointer &hpo){
/* 在减少左操作数的使用计数之前使hpo的使用计数加1,从而防止自身赋值。
如果是自身赋值,加1之后立即减1 */
++hpo.ptr->use;
--ptr->use?delete ptr;NULL;
/* 开始赋值 */
ptr=hpo.ptr;
val=hpo.val;
return *this;
}
~HasPointer(){
if(0==ptr->use)
ptr?delete ptr,ptr=NULL:NULL;
}
public:
int * get_ptr() const { return ptr->ip;}
int get_val() const { return val;}
void set_ptr( int * p) { ptr->ip = p;}
void set_val( int i) { val = i;}
int get_ptr_val() const { return *ptr->ip;}
void set_ptr_val( int i) { *ptr->ip = i;}
private:
u_pointer * ptr;
int val;
};
相应的模板类
template <typename T> class HasPU;
template<typename T>
class pHas{
friend class HasPU<T>;
pHas(T *p):pData(p),iUse(1){}
~pHas(){pData?delete pData,pdate=NULL:NULL;}
T *pData;
unsigned int iUse;
};
template<typename T>
class HasPU{
public:
HasPU(T * p,int val):pPointor(new pHas<T>(p)),iVal(val){}
HasPU(const HasPU& other){
++other.pPointor->iUse;
pPointor= other.pPointor;
iVal=other.iVal;
}
HasPU & operator=(const HasPU& oHasPU)
{
++oHasPU.pPointor->iUse;
if (0==--pPointor->iUse)
{
pPointor->data?delete pPointor->pData:NULL;
}
pPointor = oHasPU.pPointor;
iVal = oHasPU.iVal;
return *this;
}
~HasPU(){pPointor->iUse?delete pPointor:NULL;}
private:
pHas<T> * pPointor;
int iVal;
};