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,這裏就寫一點思路,具體代碼就略過了。

        

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章