在C++中,我們常用指針去使用某個對象實例,但隨著代碼對該對象使用的增加,比如越來越多的其它的類或模塊需要使用該對象,那么什么時候安全地釋放該對象就是個問題。比如,某處使用完該對象后,認為不再使用,便釋放了它,但另外的某些類或模塊還需使用,這時,就會引起內(nèi)存的非法使用問題,在Linux下是signal 11錯誤,也就是段錯誤(Segmentation Fault)。為了解決這種問題,引入了智能指針,當使用該對象時,令其引用計數(shù)加1,釋放時只是減去1。當減為0時,就自動釋放指針所指對象。C++中,通常使用模板實現(xiàn)這一機制。但是當兩個智能指針相互引用對方時,即使其它地方都釋放它們,它們的引用計數(shù)也會為1,最終導致內(nèi)存泄漏。這就引入了弱指針的概念。
Android中的隨處可見的sp<XXX>和wp<XXX>。這里的XXX是對象的類,sp和wp是模版,分別實現(xiàn)了強指針(Strong Pointer)和弱指針(Weak Pointer)。模板具體化后的一個實例XXX,具有指針的屬性,可以簡單地把它理解一個指針,只不過比普通的指針特殊一點而已。弱指針不能直接被當作指針來使用,當需要當作指針來使用時,需要使用其成員函數(shù)promote來“提升”為強指針。弱指針指向的對象可能已經(jīng)被銷毀,這時,若使用promote得到的指針為空指針。
引用計數(shù)功能的實現(xiàn)
RefBase是引用計數(shù)的基類(見文件RefBase.h),在它里面還定義了一個嵌套類weakref_type,在其實現(xiàn)文件RefBase.cpp里還定義了一個類weakref_impl ,它繼承自嵌套類weakref_type,而RefBase中包含一個私有數(shù)據(jù)成員:指向weakref_impl 的指針。可以看出,RefBase中的數(shù)據(jù)實體就是weakref_impl,后者繼承自其嵌套類weakref_type。其示意圖如下:
這樣,相當于將一部分成員函數(shù)(weakref_type的成員函數(shù))和數(shù)據(jù)成員(weakref_impl的數(shù)據(jù)成員)封裝起來,作為私有的一個邏輯實體,只被Refbase內(nèi)部的實現(xiàn)使用,而RefBase的公有成員才是外界使用的API。RefBase通過指針mRefs使用內(nèi)部的引用計數(shù)數(shù)據(jù)。而內(nèi)部引用計數(shù)實體對象也可以通過 mBase這個成員來使用其“容器”對象RefBase.
weakref_impl里面的數(shù)據(jù)成員信息如下:
volatile int32_t mStrong;//強引用計數(shù)
volatile int32_t mWeak;//弱引用計數(shù)
RefBase* const mBase; //指向其“容器”類RefBase
volatile int32_t mFlags;//對象銷毀策略標志:若為0,則強引用計數(shù)為0時即銷毀對象;若為1(OBJECT_LIFETIME_WEAK=0×0001),則強弱引用計數(shù)均為0時銷毀;若為3(OBJECT_LIFETIME_FOREVER = 0×0003),則由創(chuàng)建者管理,即不依賴RefBase引用計數(shù)。
強指針和弱指針都是模板類:
template <typename T>
class sp{
//……此處省略了部分代碼
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
//……此處省略了部分代碼
T* m_ptr;//實際指向?qū)ο蟮闹羔?/span>
};
template <typename T>
class wp{
//……此處省略了部分代碼
sp<T>promote() const;
//……此處省略了部分代碼
T* m_ptr;
weakref_type* m_refs;
};
強指針因為重載了兩個操作符*和->,因此具有形式上跟普通指針一樣的用法,而弱指則沒有重載這兩個操作符,只能先被“提升”為強指針后,才可以當作普通指針來使用。
如果需要使用智能指針將對象保護起來,只要讓其繼承RefBase,并將析構(gòu)函數(shù)聲明為virtual的,就可以使用智能指針。
可以參考鏈接來獲取詳細介紹:
參考: Android系統(tǒng)的智能指針(輕量級指針、強指針和弱指針)的實現(xiàn)原理分析
http://blog.csdn.net/luoshengyang/article/details/6786239