智能指針之輔助類

智能指針引入的目的是爲了解決懸掛指針的問題,關於懸掛指針,相信很多人都碰到過。對類中包含指針的類,在進行拷貝構造或者賦值操作時要尤其小心,但是往往很難避開懸掛指針的問題。

智能指針的實現是通過引用計數來完成的。將一個指針對象和引用計數關聯起來,使用引用計數來追蹤對象的使用。

①創建新對象時,初始化指針,並設置引用計數爲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;        // 輔助類對象
};

發佈了23 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章