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;//调用拷贝构造函数
时的过程如下图:
下面是这两个类的类图:
#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;
}