智能指針-複制構造
設計具有指針成員的類時,首先需要決定的是該指針應提供什麼行為。例如将一個指針複制到另一個指針
時,兩個指針指向同一個對象。當兩個指針指向同一對象時,可能使用任一指針改變基礎對象。類似地,很可
能一個指針删除了一對象時,另一指針的使用者還認為基礎對象仍然存在。
大多數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;
};