C++中,标准库的使用大大减少了现代C++程序中对指针的需要。然而,许多应用程序仍然需要使用指针,特别是在类的实现中,并且包含指针的类复制控制方面容易出错。
具有指针成员的对象一般需要定义复制控制成员。如果依赖合成版本,会给类的用户增加负担。用户必须保证成员所指向的对象存在,只要还有指针指向该对象。为了管理这些具有指针成员的类,必须定义三个复制控制成员:复制构造函数、赋值操作符和析构函数。这些成员可以定义指针成员的指针型行为或值型行为,或者智能指针类(需要一个使用计数类配合)。
大多数C++类采用三种方法管理指针成员。
(1)指针成员采取常规指针型行为。复制指针时只复制指针中的地址,而不会复制指针指向的对象。这样的类具有指针的所有缺陷但无需特殊的复制控制。
常规指针类:
class HasPtr{
public:
HasPtr(int *p):ptr(p){}
HasPtr(const HasPtr& Hp):ptr(Hp.ptr){}
int get_ptr()const{retrun ptr;}
void set_ptr(int *p){ptr=p;}
int get_ptr_val()const {return *ptr;}
private:
int *ptr;
}
如(出现悬垂指针!!!)
int *p=new int(10);
HasPtr ptr(p);//HasPtr points to same object as p does
delete p;//object pointed to by p is freed
ptr.set_ptr_val(0);//disaster: The object to which HasPtr points was freed!
(2)类可以实现所谓的“智能指针”(smart pointer)行为。指针所指的对象仍是共享的,但类能够防止悬垂指针(指向了不存在的对象的指针)。
解决办法:为指向同一共享对象的指针引入了一个使用计数use count:记录指向共享对象的类对象数目。初始:新创建一个类对象,使用计数初值为1。
即智能指针将一个计数器与类指向对象想关联起来。
使用计数类(有两种经典策略实现,另一种见:句柄类区别在于:类指针成员所指对象由谁直接关联(智能指针类:由使用计数类直接关联;句柄类:由句柄类自己直接关联。)):这里:定义一个单独的具体类:封装使用计数和相关指针。
class HasPtr;//智能指针类声明
class U_Ptr{ //定义为私有(class默认:private)
friend class HasPtr;//友元
int *ip;
size_t use;
U_Ptr(int *p):ip(p),use(1){}
~U_Ptr(){delete ip;}
}
智能指针类:
class HasPtr{public: HasPtr(int *p):ptr(new U_Ptr(p)){}
HasPtr(const HasPtr& Hp):ptr(Hp.ptr){++ptr->use}
int get_ptr()const{retrun ptr;}
void set_ptr(int *p){ptr=p;}
int get_ptr_val()const {return *ptr;}
HasPtr& operator=(const HasPtr&rhs)
{
++rhs.ptr->use;//可防止自身复制
if(--ptr->use==0)delete ptr;
ptr=rhs.ptr;
return *this;
}
~HasPtr(){if(ptr->use==0)delete ptr;}
private: U_Ptr *ptr;
};
(3)类采取值型行为。将指针成员所指基础值的副本给每个对象。每个指针所指向的对象是唯一的,由每个类对象独立管理。
使指针成员表现的想一个值(指针的值型行为),复制值型对象时,会得到一个不用的新副本。即复制指针所指向的对象,而不是复制指针本身。
值型类:
class HasPtr{
public:
HasPtr(const int *p):ptr(new int(*p)){}
HasPtr(const HasPtr& orig):ptr(new int (*orig.ptr)){}
HasPtr& operator=(const HasPt&rhs)
{
*ptr=*rhs.ptr;
return 0;
}
int get_ptr_val()const{return *ptr;}
int* get_ptr()const{return ptr;}
void set_ptr(int *p){ptr=p;}
~HasPtr(){delete ptr;}
private:
int *ptr;
};