c++编程提倡使用标准库,一个原因是标准库大胆减少对指针的使用。但是许多程序是离不开指针的。包含指针的类需要特别注意复制控制,原因是复制指针时只复制指针中的地址,而不复制指针所指向的对象。这样当把一个对象复制给另一个对象后,当改变一个对象后,另一个对象也会收到牵连。另外一个对象释放掉后,其指针已经被释放掉。而另一个对象还不知道,其实该对象中的指针已经成为悬垂指针。这样再操作就会出现错误。

1. 定义智能指针类

原理:定义一个计数的类,所有复制的都是指向这一个类,每复制一次,该类加1一次;每析构一次,该类减1一次。当次数为0时,释放掉动态申请的空间。

图例:

1)定义一个对象

【c++】类管理指针成员_ios

 

2)复制一个对象

【c++】类管理指针成员_ios_02

#include <iostream>
#include <string>
using namespace std;

class HasPtr;
//定义计数类
class//没有访问标号,默认为private,保证类的隐私,但是友员类可以随意访问(包括private)class HasPtr;
U_Ptr(int *p) : ip(p), use(1) {}
~U_Ptr() { cout << "hello" << use << endl; delete ip; }
int *ip;
size_t use; //次数class HasPtr
{
public:
HasPtr(int *p, int v) : ptr(new U_Ptr(p)), val(v) {}
HasPtr(const HasPtr &orig) : ptr(orig.ptr), val(orig.val) { ++ptr->use; }
HasPtr& operator=(const HasPtr &orig);
~HasPtr()
{ cout << "hahha::" << ptr->use << endl; if(--ptr->use == 0) delete ptr; }
private:
U_Ptr *ptr;
int val;
};

HasPtr& HasPtr::operator=(const HasPtr &orig)
{
++orig.ptr->use;
if(--ptr->use == 0)
delete ptr;
ptr = orig.ptr;
val = orig.val;
return *this;
}

int main()
{
int i = 56, j = 12;
int *p = new int(56);
HasPtr hasptr(p, j);
HasPtr hasptr2(hasptr);

2. 定义值型类

给指针成员提供语义值。具有值语义的类所定义的对象,其行为很像算术类型的对象:复制值型对象时,会得到一个不同的版本。对副本的改变不会反映在原有对象上。

#include <iostream>
#include <string>
using namespace std;

class HasPtr
{
public:
HasPtr(const int &p, int v) : ptr(new int(p)), val(v) {}
HasPtr(const HasPtr &orig) : ptr(new int(*orig.ptr)), val(orig.val) { } //复制值型对象时,会得到一个不同的版本& operator=(const HasPtr &orig);
~HasPtr() { delete ptr; }
private:
int *ptr;
int val;
};

HasPtr& HasPtr::operator=(const HasPtr &orig)
{
*ptr = *orig.ptr; //赋值时,只改变指针指向的值,但是指针是不变的= orig.val;
return *this;
}

int main()
{
int i = 56, j = 12;
HasPtr hasptr(i, j);
HasPtr hasptr2(hasptr);
hasptr2 = hasptr;
}