指针问题是在学习C++,以及运用C++进行软件开发过程中经常碰到的问题。其中之一,就是“悬垂指针”。所谓悬垂指针,就是是指指针指向了一块没有分配给用户使用的内存,结果未定义,往往导致程序错误,而且难以检测。
用一个简单的例子来说明悬垂指针:
string *sp = new string("Test dangling pointer");
string *dp = sp;
delete sp;
//此时会发生严重的错误
delete dp;
由于指针dp所指向的内存单元已经被指针sp释放,再次释放将会产生严重的问题
为了解决C++中悬垂指针的问题,引入“智能指针(smart pointer)”的概念。定义智能指针的通用技术是采用一个“使用计数”。
图示说明:
智能指针类将一个计数器与类指向的对象相关联,使用计数跟踪该类有多少个对象共享同一指针。
1. 定义智能指针类,假设基础对象为string类型的对象
//定义只能指针类smartPtr
class smartPtr
{
public:
//构造函数
smartPtr(std::string *p): ptr(new cntPtr(p)) { }
//复制构造函数
smartPtr(const smartPtr &orig): ptr(orig.ptr) { ++ptr->cnt; }
//赋值操作符
smartPtr& operator=(const smartPtr&);
//析构函数
~smartPtr()
{
//只有在删除最后一个指向基础对象的指针时才释放基础对象
if (--ptr->cnt == 0)
{
delete ptr;
}
}
private:
cntPtr *ptr;
};
2. 定义使用计数类
//定义使用计数类cntPtr
class cntPtr
{
//声明智能指针类smartPtr为其友元类
friend class smartPtr;
//指向string类型对象的指针sp
std::string *sp;
//计数器cnt
std::size_t cnt;
//构造函数
cntPtr(std::string *p): sp(p), cnt(1) { }
~cntPtr() { delete sp; }
};
3. 此时运行
smartPtr t_sp_1(new string("Test smart pointer"));
smartPtr t_sp_2 = t_sp_1;
//显式调用析构函数(不推荐)
t_sp_1.~smartPtr();
t_sp_2.~smartPtr();
将不会出现任何错误。