天天看點

智能指針 smart pointer

                                                                                                  智能指針-複制構造

       設計具有指針成員的類時,首先需要決定的是該指針應提供什麼行為。例如将一個指針複制到另一個指針

時,兩個指針指向同一個對象。當兩個指針指向同一對象時,可能使用任一指針改變基礎對象。類似地,很可

能一個指針删除了一對象時,另一指針的使用者還認為基礎對象仍然存在。

大多數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;
};