欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c++引用计数的本质 博客分类: c/c++  

程序员文章站 2024-02-07 10:21:58
...

为什么要用引用计数? 

       场景:代码里X是一个非常重要的资源,模块A,B,C都有对其指针的引用,那么为了不出现内存泄露,常规的代码我们要怎么写?

               1. A 模块用完X时,需要检查B,C是否还在引用X,如果B,C有一个在用,那么X只要删除掉对A的引用就可以了,

                  如果B,C对A都已经没有引用了,那么A需要删除对X的引用时,要同时清除掉X。

               2.同样B,C在用完X时,也要重复做1里面的事情。

                 这样,代码将会多了许多的逻辑判断,同时模块B,C还需要对模块A提供查询是否在引用X的接口。

        可以不这么恶心吗?

        思考:能否A在释放X前,不需要知道是谁在引用X,只要知道有多少人在引用X?

        回答:是的,如果只有我用X,那么我就直接删除,如果还有其他人用,我就什么都不管,只要去除掉对X的引用就可以了。  情况就会变的好一些。

        那么如何做到能知道资源的引用次数那?

        这就需要对每一个资源X的都有一个的计数,这个计数是和资源X的生命周期息息相关的。

        那么如何来管理这个计数?怎么能在有模块引用资源X的时候,计数++,模块释放资源X的时候计数--那?

        这个就有一定难度了,引用的方式会有很多种,比如  A = X;   A.push_back(X);  A[100] = X; ...

        当然我们可以在代码里的每一处增加和释放资源引用的地方,都加上代码count++,count--;但这亦然很麻烦,维护成本很高。

        如何简单些?

        能否把对资源的引用和释放,看成是对一个类的拷贝和销毁来完成? 弄一个代理类,里面封装好计数和资源X。

        把所有对资源X的引用都理解成对代理类的引用,对代理类的引用都理解成对代理类的拷贝,对代理的释放就是销毁代理类。

        这样我们只需要在代理类的拷贝函数里count++ , 代理类的析构做count--就好了。

        如果代理类的资源引用计数count 减为0,就看成所有人都释放了对资源X的引用,这时由代理类来完成对资源的销毁。

        这样下来,事情就简化了很多。 所以学会抽象是多么重要的一件事情。

        一点code:

c++引用计数的本质
            
    
    博客分类: c/c++  
class RefPtr
{
     size count;
     X * ptr;    
}
class Proxy
{
       RefPtr* ptr;    
};
c++引用计数的本质
            
    
    博客分类: c/c++  

        1 Proxy里面需要重载=, 拷贝构造

        2 Proxy需要提供访问ptr的接口

        3 Proxy需要在拷贝的地方增加计数,析构的时候判断是否删除ptr

        --- ko,这里就写一点思路,具体代码就略过了。