当有几个对象 共同用一个资源时,则它们同时指向了这个资源,如果用普通的指针,则在其中一个对象析构时就会将这个共用的资源销毁,有了智能指针就不用担心,它里面有对象计数,代表有几个对象在用它,销毁一个就减1,直到为0,为0时就表示没有对象用这个资源了,就会自动释放资源存储区!
引入智能指针后:
引入智能指针可以防止出现悬垂指针的情况一般是把指针封装到一个称之为智能指针类中,这个类中另外还封装了一个使用计数器,对指针的复制等操作将导致该计数器的值加1,对指针的delete操作则会减1,值为0时,指针为NULL。
举例如下:
class HasPtr{
public:
HasPtr(int *p,int i):ptr(p),val(i){}
int *get_ptr() const {return ptr;}
int get_int() const {return val;}
void set_ptr(int *p){ptr=p;}
void set_int(int i){val=i;}
int get_ptr_val() const {return *ptr;}
void set_ptr_val(int val) const{*ptr=val;}
private:
int *ptr;
int val;
};
int *ip =new int(42);
HasPtr ptr(ip,10);
delete ip;
ptr.set_ptr_val(0);
这里的问题是ip和ptr中的指针指向同一对象。删除了该对象后,ptr中的指针不再指向有效对象,从而造成悬垂指针。
如何定义智能指针类:
1、定义计数类
class U_ptr{
friend class HasPtr;
int *ip;
size_t use;
U_ptr(int *p):ip(p),use(1){}
~U_ptr(){delete ip;}
};
2、使用计数类
class HasPtr{
public:
HasPtr(int *p,int i):ptr(new U_ptr(p)),val(i){}
//复制构造函数
HasPtr(const HasPtr &has):ptr(has.ptr),ival(has.ival){++ptr->use;}
//赋值操作符
HasPtr& operator=(const HasPtr &);
//析构函数
~HasPtr(){if(--ptr->use==0)delete ptr;}
private:
U_ptr *ptr;
int val;
};
HasPtr& HasPtr::operator=(const HasPtr &has)
{
//右操作数计数器加1
++has->use;
//左操作数计数器减1
if(--ptr->use==0)
delete ptr;
ptr=has.ptr;
val=has.val;
return *this;
}
复制构造函数将指针从旧对象复制到新对象时,会将使用计数加1;
赋值操作符将左操作数的使用计数减1,并将右操作数的使用计数加1,如果左操作数的使用计数减至0时,赋值操作符必须删除它所指向的对象。
析构函数将使用计数减1,并且,如果使用计数减至0,就删除基础对象。