C++ 引用计数

C++没有像java那样的垃圾回收机制,但是我们可以实现一个。一种很简单的方式就是使用引用计数。它实际上是一种用对象来管理资源的方式,因为普通的栈上的对象在离开作用域时会调用对应的析构函数,根据这个特性,可以实现用于对指针进行管理的类。

下面以一个对int*指针的管理来说明引用计数是如何实现的。

当我们创建一个int型指针时:int *p=new int(10);

在最后我们需要调用delete p;

通过接下来指定的方式,我们可以不用显示调用delete p;这行代码而又能够释放掉通过new关键字分配的内存,就是通过引用来实现的。

先列出下面一张图表:


上面是我们需要使用的int*指针以及需要定义的两个类Referenced和Ref_ptr类,其实Referenced类对用户而言是不可见的,就是用户在使用引用计数的过程中都不会用到这个类,这个类只在Ref_ptr内部被调用。

执行Ref_ptr r1=new int(4);//调用构造函数

Ref_ptr r2=r1;//调用拷贝构造函数

时的过程如下图:


下面是这两个类的类图:


C++代码:


#include <iostream>
#include <string>

using namespace std;

class Referenced 
{
public:
	//初始化这个类,引用计数设为1,并且将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,根据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
	}

	//赋值操作符,右操作数的引用计数要减1,左操作数的引用计数要加1
	Ref_ptr & operator=(const Ref_ptr & rhs)
	{
		if(&rhs==this)
			return *this;
		if(ptr->unref()==0)//赋值操作符,首先将当前类的引用计数减1
		{
			cout<<"delete Ref_ptr"<<endl;
			delete ptr;
		}
		ptr=rhs.ptr;//将右操作数的引用计数赋值给当前对象
		ptr->ref();//引用计数加1
		return *this;
	}

	//析构函数,引用计数要减1,如果减为0,删除这块内存
	~Ref_ptr()
	{
		if(ptr->unref()==0)
		{
			cout<<"delete Ref_ptr"<<endl;
			delete ptr;
		}
	}
private:
	Referenced * ptr;
};

int main()
{
	//Referenced rd=new int(4);
	Ref_ptr r=new int(4);
	Ref_ptr r1=new int(5);
	r=r1;

	getchar();
	return 0;
}


阅读更多
换一批

没有更多推荐了,返回首页