Android智能指針使用方法介紹
Android手機(jī)操作系統(tǒng)既然是開(kāi)源的操作系統(tǒng)。那么在具體的文件夾中就會(huì)存放著各種相關(guān)功能的開(kāi)源代碼。我們?cè)谑褂玫臅r(shí)候可以根據(jù)這些源代碼進(jìn)行相應(yīng)的修改就能輕松的完成我們所需的功能。在這里大家就一起來(lái)看看Android智能指針的相關(guān)源碼解讀以及應(yīng)用方法。#t#
在Android的源代碼中,經(jīng)常會(huì)看到形如:sp< xxx>、wp< xxx>這樣的類型定義,這其實(shí)是Android中的智能指針。智能指針是C++中的一個(gè)概念,通過(guò)基于引用計(jì)數(shù)的方法,解決對(duì)象的自動(dòng)釋放的問(wèn)題。在C++編程中,有兩個(gè)很讓人頭痛的問(wèn)題:一是忘記釋放動(dòng)態(tài)申請(qǐng)的對(duì)象從而造成內(nèi)存泄露;二是對(duì)象在一個(gè)地方釋放后,又在別的地方被使用,從而引起內(nèi)存訪問(wèn)錯(cuò)誤。
程序員往往需要花費(fèi)很大精力進(jìn)行精心設(shè)計(jì),以避免這些問(wèn)題的出現(xiàn)。在使用智能指針后,動(dòng)態(tài)申請(qǐng)的內(nèi)存將會(huì)被自動(dòng)釋放(有點(diǎn)類似Java的垃圾回收),不需要再使用delete來(lái)釋放對(duì)象,也不需要考慮一個(gè)對(duì)象是否已經(jīng)在其它地方被釋放了,從而使程序編寫(xiě)工作減輕不少,而程序的穩(wěn)定性大大提高。
Android智能指針相關(guān)的源代碼在下面兩個(gè)文件中:
frameworks\base\include\utils\RefBase.h
frameworks\base\libs\utils\RefBase.cpp
Android中定義了兩種智能指針類型,一種是強(qiáng)指針sp(strong pointer),一種是弱指針(weak pointer)。其實(shí)成為強(qiáng)引用和弱引用更合適一些。強(qiáng)指針與一般意義的智能指針概念相同,通過(guò)引用計(jì)數(shù)來(lái)記錄有多少使用者在使用一個(gè)對(duì)象,如果所有使用者都放棄了對(duì)該對(duì)象的引用,則該對(duì)象將被自動(dòng)銷毀。
弱指針也指向一個(gè)對(duì)象,但是弱指針僅僅記錄該對(duì)象的地址,不能通過(guò)弱指針來(lái)訪問(wèn)該對(duì)象,也就是說(shuō)不能通過(guò)弱智真來(lái)調(diào)用對(duì)象的成員函數(shù)或訪問(wèn)對(duì)象的成員變量。要想訪問(wèn)弱指針?biāo)赶虻膶?duì)象,需首先將弱指針升級(jí)為強(qiáng)指針(通過(guò)wp類所提供的promote()方法)。弱指針?biāo)赶虻膶?duì)象是有可能在其它地方被銷毀的,如果對(duì)象已經(jīng)被銷毀,wp的promote()方法將返回空指針,這樣就能避免出現(xiàn)地址訪問(wèn)錯(cuò)的情況。
是不是很神奇?弱指針是怎么做到這一點(diǎn)的呢?其實(shí)說(shuō)穿了一點(diǎn)也不復(fù)雜,原因就在于每一個(gè)可以被智能指針引用的對(duì)象都同時(shí)被附加了另外一個(gè) weakref_impl類型的對(duì)象,這個(gè)對(duì)象中負(fù)責(zé)記錄對(duì)象的強(qiáng)指針引用計(jì)數(shù)和弱指針引用計(jì)數(shù)。這個(gè)對(duì)象是Android智能指針的實(shí)現(xiàn)內(nèi)部使用的,智能指針的使用者看不到這個(gè)對(duì)象。弱指針操作的就是這個(gè)對(duì)象,只有當(dāng)強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)都為0時(shí),這個(gè)對(duì)象才會(huì)被銷毀。
說(shuō)了這么多原理,下面該看看到底智能指針該怎么使用了。假設(shè)現(xiàn)在有一個(gè)類MyClass,如果要使用智能指針來(lái)引用這個(gè)類的對(duì)象,那么這個(gè)類需滿足下列兩個(gè)前提條件:
(1) 這個(gè)類是基類RefBase的子類或間接子類;
(2) 這個(gè)類必須定義虛構(gòu)造函數(shù),即它的構(gòu)造函數(shù)需要這樣定義:
- virtual ~MyClass();
滿足了上述條件的類就可以定義Android智能指針了,定義方法和普通指針類似。比如普通指針是這樣定義:
- MyClass* p_obj;
Android智能指針是這樣定義:
- sp< MyClass> p_obj;
注意不要定義成 sp< MyClass>* p_obj。初學(xué)者容易犯這種錯(cuò)誤,這樣實(shí)際上相當(dāng)于定義了一個(gè)指針的指針。盡管在語(yǔ)法上沒(méi)有問(wèn)題,但是最好永遠(yuǎn)不要使用這樣的定義。
定義了一個(gè)智能指針的變量,就可以象普通指針那樣使用它,包括賦值、訪問(wèn)對(duì)象成員、作為函數(shù)的返回值、作為函數(shù)的參數(shù)等。比如:
- p_obj = new MyClass();
- // 注意不要寫(xiě)成 p_obj = new sp< MyClass>
- sp< MyClass> p_objp_obj2 = p_obj;
- p_obj->func();
- p_obj = create_obj();
- some_func(p_obj);
注意不要試圖delete一個(gè)Android智能指針,即 delete p_obj。不要擔(dān)心對(duì)象的銷毀問(wèn)題,智能指針的最大作用就是自動(dòng)銷毀不再使用的對(duì)象。不需要再使用一個(gè)對(duì)象后,直接將指針賦值為NULL即可:
- p_obj = NULL;
上面說(shuō)的都是強(qiáng)指針,弱指針的定義方法和強(qiáng)指針類似,但是不能通過(guò)弱指針來(lái)訪問(wèn)對(duì)象的成員。下面是弱指針的示例:
- wp< MyClass> wp_obj = new MyClass();
- p_obj = wp_obj.promote();
- // 升級(jí)為強(qiáng)指針。不過(guò)這里要用.而不是->,真是有負(fù)其指針之名啊
- wp_obj = NULL;
Android智能指針用起來(lái)是很方便,在一般情況下最好使用智能指針來(lái)代替普通指針。但是需要知道一個(gè)智能指針其實(shí)是一個(gè)對(duì)象,而不是一個(gè)真正的指針,因此其運(yùn)行效率是遠(yuǎn)遠(yuǎn)比不上普通指針的。所以在對(duì)運(yùn)行效率敏感的地方,最好還是不要使用智能指針為好。