以后會多寫些本質論的文章,這樣可以更好的引導自己去深入思考。
為什么要用引用計數?
場景:代碼里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,這里就寫一點思路,具體代碼就略過了。