当构造的类中含有指针的时候,常用的操作是使用智能指针。有两种经典策略,这里讲的是第一种。思维导图:
思路解释:假如Mem类有一个int *的指针,我们可以把这个指针放在另外一个类中,就是u_ptr类。用u_ptr *代替int*放在Mem中。u_ptr中多了一个计数器。这样,每次完成复制和赋值的时候,可以使各Mem对象指向同一个u_ptr的对象,而且在复制和赋值,析构过程中,完成use_count的更新,use_count保存的是同时使用int p的Mem对象的个数。
下面是具体的一个事例:
class HasPtrt { public: HasPtr(int *p,int i):ptr(new U_Ptr(p)),val(i); HasPtr(const HasPtr &orig):ptr(orig.ptr),val(orig.val) {++ptr->use;} HasPtr &operator=(const HasPtr&); ~HasPtr(){if(--ptr->use==0 delete ptr;} private: U_Ptr *ptr; int val; } //下面是U_ptr类 class U_Ptr { friend class HasPtr; int *ip; size_t use; U_Ptr (int *p):ip(p),use_count(1){} ~U_Ptr() {delete ip;} } //函数解析 //HasPtr使用int *和int两个参数进行构造。U_ptr使用一个int *进行构造。 //HasPtr(int *p,int i):ptr(new U_Ptr(p)),val(i); //ptr(new U_Ptr(p)),这个U_Ptr(p)调用构造函数构造了一个U_Ptr对象,并用new分配了内存 //最后调用复制函数,把构造出来的指针传给ptr。将计数器复位为1、 //HasPtr的复制构造函数 HasPtr(const HasPtr &orig):ptr(orig.ptr),val(orig.val) {++ptr->use;} //复制的时候,新创建的对象与原有的对象指向同一个U_Ptr对象,该U_Ptr对象的计数器加1. //赋值构造函数 HasPtr &HasPtr::operator=(const HasPtr &rhs) { ++rhs.ptr->use;//防止对自身赋值 if(--ptr->use==0) delete ptr;//将左操作数对象的use_count减1,如果为0,析构左操作数所拥有的ptr; ptr=rhs.ptr; val=rhs.val//完成赋值 return *this; }