`
king_c
  • 浏览: 213932 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

c++引用计数的本质

 
阅读更多

为什么要用引用计数? 

       场景:代码里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:

复制代码
class RefPtr
{
     size count;
     X * ptr;    
}
class Proxy
{
       RefPtr* ptr;    
};
复制代码

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

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

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

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

        

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics