第13章 复制控制(6)
13.5 管理指针成员
复制指针时只复制指针中的地址,而不会复制指针指向的对象。
大多数C++类采用以下三种方法之一管理指针成员:
(1)指针成员采用常规指针型行为。这样的类具有指针的所有缺陷但无需特殊的复制控制。
(2)类可以实现所谓的"智能指针"行为。指针所指向的对象是共享的,但类能够防止垂悬指针。
(3)类采取值型行为。指针所指向的对象是唯一的,由每个类对象独立管理。
1. 一个带指针成员的简单类
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;
};
2. 默认复制/赋值与指针成员
int obj = 0;
HasPtr ptr1(&obj, 42);
HasPtr ptr2(ptr1);
具有指针成员且使用默认合成复制构造函数的类具有普通指针的所有缺陷。尤其是,类本身无法避免垂悬指针。
3. 指针共享同一对象
ptr1.set_ptr_val(45);
cout << ptr2.get_ptr_val() << endl; //45
两个指针指向同一对象时,其中任意一个都可以改变共享对象的值。
4. 可能出现垂悬指针
int *p = new int(42);
HasPtr ptr3(p, 42);
delete p;
13.5.1 定义智能指针类
1. 引入使用计数
定义智能指针的通用技术是采用一个使用计数(use count)。智能指针类将一个计数器与类指向的对象相关联。使用计数跟踪该类有多少个对象共享同一指针。使用计数为0时,删除对象。使用计数有时也称为引用计数(reference count)。
2. 使用计数类
class U_Ptr
{
friend class HasPtr;
int *ip;
size_t use;
U_Ptr(int *p):ip(p),use(1){}
~U_Ptr(){ delete ip; }
};
3. 使用计数类的使用
class HasPtr
{
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;
};
4. 赋值与使用计数
HasPtr &HasPtr::operator= (const HasPtr &hasptr)
{
++hasptr.ptr->use;
if(--ptr->use==0) //delete the old ptr if it's reference count is 1.
delete ptr;
ptr = hasptr.ptr; //copy the new ptr value.
val = hasptr.val;
return *this;
}
这个赋值操作符在减少左操作数的使用计数之前使rhs的使用计数加1,从而防止自身赋值。
5. 改变其他成员
class HasPtr
{
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;
}
int *get_ptr() const{ return ptr->ip; }
int get_int() const{ return val; }
void set_ptr(int *p){ ptr->ip=p; }
void set_int(int i){ val=i; }
int get_ptr_val() const{ return *(ptr->ip);}
void set_ptr_val(int val) const {*(ptr->ip) = val;}
private:
U_Ptr *ptr;
int val;
};
为了管理具有指针类型成员的类,必须定义三个复制控制成员:复制构造函数、赋值操作符和析构函数。这些成员可以定义指针成员的指针型行为或值型行为。
值型类将指针成员所指基础值的副本给每个对象。复制构造函数分配新元素并从复制对象处复制值,赋值操作符撤销所保存的原对象并从右操作数向左操作数复制值,析构函数撤销对象。
摘自 xufei96的专栏
补充:软件开发 , C++ ,