1. 程式人生 > >C++ :引用計數(reference count) 實現

C++ :引用計數(reference count) 實現

referecen count 的核心思維:使用一個計數器來標識當前指標指向的物件被多少類的物件所使用(即記錄指標指向物件被引用的次數)

  • 建構函式中建立類的新物件時,初始化引用計數為1;
  • 拷貝建構函式複製指標,並使相應的引用計數增加1;
  • 賦值操作減少左運算元所值物件的引用計數,增加右運算元所指物件的引用計數;
  • 解構函式使引用計數減少1,並且當引用計數為1時,釋放指標說指向的物件;

使用引用計數實現智慧指標的關鍵是,引用計數應該存在哪裡

引用計數應該是某個類物件和其複製物件共享的, 而指標成員恰好有這樣的特性, 故可以在類中多宣告一個int * 的成員,用來表示引用計數

程式碼實現:

#include<iostream>
#include<string>

using namespace std;

class Referenced
{
public:
	//首先初始化這個類,引用計數置為一,並且將地址賦給p
	Referenced(int *pi)
	{
		refCount = 1;
		p = pi;
	}
	//計數器+1
	int ref()
	{
		return ++refCount;
	}
	//計數器-1
	int unref()
	{
		return --refCount;
	}
	//返回引用計數
	int count()
	{
		return refCount;
	}
	//解構函式:釋放記憶體
	Referenced()
	{
		cout << "delete referenced" << endl;
		delete p;
	}
private:
	int refCount;//計數器:表示有多少個變數引用這塊記憶體
	int *p;      //實際指標
};
//對指標進行管理的類,有一個Referenced類的指標ptr
//根據指標中的引用計數來判斷是否呼叫delete來刪除指標ptr
class Ref_ptr
{
public:
	//使用int *指標初始化ptr,必須要放在初始化列表中
	Ref_ptr(int *i) :ptr(new Referenced(i))
	{
	}
	//拷貝建構函式,另一個指標變數指向這塊區域
	Ref_ptr(const Ref_ptr& rhs)
	{
		ptr = rhs.ptr;//將右運算元的引用計數物件賦值給左運算元
		ptr->ref();   //將其引用計數+1
	}
	//賦值操作,右運算元的引用計數減一,左運算元的引用計數要加一
	Ref_ptr& operator=(const Ref_ptr& rhs)
	{
		//自己給自己賦值直接返回
		if (&rhs == this)
		{
			return *this;
		}
		//賦值操作符,首先給當前類的引用計數減一
		if (ptr->unref() == 0)
		{
			cout << "delete Ref_ptr " << endl;
			delete ptr;
		}
		//將右運算元的引用計數賦值給當前的物件
		ptr = rhs.ptr;
		//引用計數加一
		ptr->ref();
		return *this;
	}
	//解構函式,引用計數減為0,刪除這快記憶體
	~Ref_ptr()
	{
		if (ptr->unref() == 0)
		{
			cout << "delete Ref_ptr" << endl;
			delete ptr;
		}
	}
private:
	Referenced * ptr;
};