原址: https://blog.csdn.net/u012501459/article/details/48229399
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; }