爲什麼要用引用計數?
場景:代碼裏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,這裏就寫一點思路,具體代碼就略過了。