智能指针之辅助类

智能指针引入的目的是为了解决悬挂指针的问题,关于悬挂指针,相信很多人都碰到过。对类中包含指针的类,在进行拷贝构造或者赋值操作时要尤其小心,但是往往很难避开悬挂指针的问题。

智能指针的实现是通过引用计数来完成的。将一个指针对象和引用计数关联起来,使用引用计数来追踪对象的使用。

①创建新对象时,初始化指针,并设置引用计数为1;

②当对象作为另外一个对象的副本创建,也就是调用拷贝构造函数时,拷贝指针,并且,增加引用计数;

③当对一个对象进行赋值时,左操作数所指对象的引用计数减少,如果减少为0,则删除对象,右操作数所指对象的引用计数增加;

④调用析构函数,减少引用计数,如果减至0,则删除指针。


引用计数的实现由两种经典策略:引入辅助类和使用句柄。分两篇内容详细说明。
首先介绍引入辅助类的方法。

先上一张图,从这个图中可以看出大概的思路。


使用U_Ptr作为辅助类,其实是一个模板类,封装实际的指针对象,和引用计数值。在使用时,不会直接使用这个类,由HasPtr使用。HasPtr是一个模板类,作为对外使用的类,构造时传入实际的指针对象。内部包含了一个辅助类U_Ptr的指针对象,多个HasPtr类对象指向同一个U_Ptr对象,U_Ptr依靠引用计数来实现实际指针对象的释放。

//模板类作为友元类,要事先声明
template <class T> 
class HasPtr;

//辅助类
template<typename T>
class U_Ptr {
	friend class HasPtr<T>;	//友元类

	T *ip;	//实际指针对象

	size_t use;	//引用计数

	U_Ptr(T *p)
		:ip(p), use(1)
	{ }

	~U_Ptr() 
	{
		delete ip;
	}
};

template<typename T>
class HasPtr 
{
public:
	// 构造函数,引用计数初始化为1
	explicit HasPtr(T *p)
		:ptr(new U_Ptr<T>(p))
	{ }

	// 拷贝构造函数,引用计数加1
	HasPtr(const HasPtr<T> &orig)
		:ptr(orig.ptr)
	{
		++ptr->use;
	}

	//赋值
	HasPtr<T>& operator=(const HasPtr<T>& rhs)
	{
		++rhs.ptr->use;     // 操作符右值自加
		if (--ptr->use == 0)	//左值自减,并判断是否减至0
			delete ptr;    // 减至0则删除
		ptr = rhs.ptr;      // 拷贝指针
		return *this;

	}

	// 析构,自减
	~HasPtr()
	{ 
		if (--ptr->use == 0)
			delete ptr;
	}

	//其他操作符,如->、*等略去
private:
	U_Ptr<T> *ptr;        // 辅助类对象
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值