第一章 自動(dòng)引用計(jì)數(shù)
?1.1 定義
自動(dòng)引用計(jì)數(shù)(ARC,Automatic Reference Counting)是指內(nèi)存管理中對(duì)引用采取自動(dòng)計(jì)數(shù)的技術(shù)。
*在 LLVm 編譯器中設(shè)置 ARC 為有效狀態(tài),就無需再次鍵入 retain 或者是 release 代碼。*
?1.2內(nèi)存管理/引用計(jì)數(shù)
?1.2.1概要
引用計(jì)數(shù)的機(jī)制相當(dāng)于開關(guān)房間的燈
1. 最早進(jìn)入辦公室的人開燈
2. 之后進(jìn)入辦公室的人,需要照明
3. 下班離開辦公室的人,不需要照明
4. 最后離開辦公室的人關(guān)燈(此時(shí)已無人需要照明)
判斷是否有人還在辦公室里,關(guān)鍵在于導(dǎo)入計(jì)數(shù)功能計(jì)算需要照明的人數(shù)。
1. 第一個(gè)人進(jìn)入辦公室,需要照明的人數(shù)加1.計(jì)數(shù)值從0編程了1,因此開燈
2. 之后每當(dāng)有人進(jìn)來,需要照明的人數(shù)就加1.
3. 每當(dāng)有人下班離開,需要照明的人數(shù)就減1.
4. 最后一個(gè)人下班離開辦公室時(shí),需要照明的人數(shù)減1,計(jì)數(shù)值從1變成0,因此要關(guān)燈
*對(duì)比*
```
對(duì)照明設(shè)備所做的動(dòng)作 對(duì) Objective-C 對(duì)象所做的動(dòng)作
開燈 生成對(duì)象
需要照明 持有對(duì)象
不需要照明 釋放對(duì)象
關(guān)燈 廢棄對(duì)象
```
?1.2.2 內(nèi)存管理的思考方式
* 自己生成的對(duì)象,自己所持有
* 非自己生成的對(duì)象,自己也能持有
* 不再需要自己持有的對(duì)象時(shí)釋放
* 非自己持有的對(duì)象無法釋放
```
對(duì)象操作與 Objective-C 方法的對(duì)應(yīng)
生成并持有對(duì)象 alloc/new/copy/mutablecopy 等
持有對(duì)象 retain方法
釋放對(duì)象 release 方法
廢棄對(duì)象 dealloc 方法
```
Cocoa 框架中的 Foundation 框架類庫的 NSObject 類擔(dān)負(fù)內(nèi)存管理的職責(zé)。
詳細(xì)了解內(nèi)存管理的思考方式中出現(xiàn)的各個(gè)項(xiàng)目:
*自己生成的對(duì)象,自己持有*
自己指對(duì)象的使用環(huán)境,也可以指編程人員自身
以下名稱開頭的方法自己生成自己持有
* alloc(自己生成并持有對(duì)象)
* new
* copy(生成不可變更的對(duì)象)
* mutablecopy(生成可變更的對(duì)象)
*非自己生成的對(duì)象,自己也能持有*
id obj = [NSMutableArray array];
[obj retain];
非自己生成的對(duì)象通過 retain 方法可以自己持有
*不再需要自己持有的對(duì)象時(shí)釋放*
* 自己生成并持有的對(duì)象,釋放時(shí)使用 release
* 自己生成但不持有的對(duì)象,使用 autorelease 釋放,autorelease 可以使對(duì)象在超出指定的生存范圍時(shí)能夠自動(dòng)并正確釋放
*無法釋放非自己持有的對(duì)象*
釋放之后無法再次釋放對(duì)象,也無法訪問
?alloc/retain/release/dealloc 實(shí)現(xiàn)
內(nèi)存之區(qū)域 — NSZone
是為防止內(nèi)存碎片化而引入的結(jié)構(gòu),對(duì)內(nèi)存分配的區(qū)域本身進(jìn)行多重化管理,根據(jù)使用對(duì)象的目的、對(duì)象的大小分配內(nèi)存,從而提高了內(nèi)存管理的效率。
ARC 下使用區(qū)域管理內(nèi)存反而會(huì)引起內(nèi)存使用效率低下以及源代碼復(fù)雜化等問題
源碼總結(jié):
* 在 Objective-C 的對(duì)象中存有引用計(jì)數(shù)這一整數(shù)值
* 調(diào)用 alloc 或是 retain 方法后,引用計(jì)數(shù)值加1
* 調(diào)用 release 后,引用計(jì)數(shù)值減1
* 引用計(jì)數(shù)值為0時(shí),調(diào)用 dealloc 方法廢棄對(duì)象
1.2.3 蘋果的實(shí)現(xiàn)
GNUstep采用將引用計(jì)數(shù)保存在對(duì)象占用內(nèi)存塊頭部的變量中,? 則是保存在引用計(jì)數(shù)表的記錄。
內(nèi)存塊頭部管理引用計(jì)數(shù)的好處:
* 少量代碼即可完成
* 能夠統(tǒng)一管理引用計(jì)數(shù)用內(nèi)存塊與對(duì)象用內(nèi)存塊
引用計(jì)數(shù)表管理引用計(jì)數(shù)的好處:
* 對(duì)象用內(nèi)存塊的分配無需考慮內(nèi)存塊頭部
* 引用計(jì)數(shù)表各記錄中存有內(nèi)存塊地址,可從各個(gè)記錄追溯到各對(duì)象的內(nèi)存塊
1.2.5 autorelease
autorelease 就是自動(dòng)釋放,相當(dāng)于 C 語言中的自動(dòng)變量,程序執(zhí)行時(shí),若某自動(dòng)變量超出其自動(dòng)域,該自動(dòng)變量將被自動(dòng)廢棄。想當(dāng)于會(huì)自動(dòng)調(diào)用 release 方法。
使用方法:
1. 生成并持有 NSAutoreleasePool 對(duì)象
2. 調(diào)用已分配對(duì)象的 autorelease 實(shí)例方法
3. 廢棄 NSAutoreleasePool對(duì)象
NSAutoreleasePool 由程序主循環(huán)的NSRunLoop 或者在其他程序可運(yùn)行的地方,對(duì) NSAutoreleasePool 對(duì)象進(jìn)行生成、持有和廢棄處理。