內存管理機制


Objective-C中提供了兩種內存管理機制MRC(MannulReference Counting)和ARC(Automatic Reference Counting),分別提供對內存的手動和自動管理,來滿足不同的需求.

 

ARC:

 

ARC是Auto Reference Counting的縮寫,即自動引用計數,由編譯器在代碼合適的位置中自動添加retain/Release/Autorelease/dealloc方法從而進行內存管理.

 

ARC幾個要點:

 

  • 在對象被創建時 retain count +1,在對象被release時 retain count -1.當retain count 為0 時,銷毀對象。
  • 程序中加入autoreleasepool的對象會由系統自動加上autorelease方法,如果該對象引用計數為0,則銷毀。

 

那么ARC是為了解決什么問題誕生的呢?這個得追溯到MRC手動內存管理時代說起。

 

MRC下內存管理的缺點:

 

  • 當我們要釋放一個堆內存時,首先要確定指向這個堆空間的指針都被release了。(避免提前釋放)
  • 釋放指針指向的堆空間,首先要確定哪些指針指向同一個堆,這些指針只能釋放一次。(MRC下即誰創建,誰釋放,避免重復釋放)
  • 模塊化操作時,對象可能被多個模塊創建和使用,不能確定最后由誰去釋放。
  • 多線程操作時,不確定哪個線程最后使用完畢

 

 

 

 

在ARC中與內存管理有關的標識符,可以分為變量標識符(_strong,  _weak, _unsafe_unretained, autoreleasing)和屬性標識符(nonatomic/atomic, assign/retain/strong/weak/unsafe_unretained/copy,readonly/readwrite),對於變量默認為__strong,而對於屬性默認為unsafe_unretained。也存在autoreleasepool。

 

 其中assign/retain/copy與MRC下property的標識符意義相同,strong類似與retain,assign類似於unsafe_unretained,strong/weak/unsafe_unretained與ARC下變量標識符意義相同,只是一個用於屬性的標識,一個用於變量的標識(帶兩個下划短線__)。所列出的其他的標識符與MRC下意義相同。

 

(1)對於assign,你可以對標量類型(如int)使用這個屬性。你可以想象一個float,它不是一個對象,所以它不能retain、copy。

 

(2)對於copy,指定應該使用對象的副本(深度復制),前一個值發送一條release消息。基本上像retain,但是沒有增加引用計數,是分配一塊新的內存來放置它。特別適用於NSString,如果你不想改變現有的,就用這個,因為NSMutableString,也是NSString。

 

 

 

MRC:

在MRC的內存管理模式下,與對變量的管理相關的方法有:retain,release和autorelease。retain和release方法操作的是引用記數,當引用記數為零時,便自動釋放內存。並且可以用NSAutoreleasePool對象,對加入自動釋放池(autorelease調用)的變量進行管理,當drain時回收內存。

 

Strong 和 Weak 的區別:

強引用持有對象,弱引用不持有對象。 

強引用可以釋放對象,但弱引用不可以,因為弱引用不持有對象,當弱引用指向一個強引用所持有的對象時,當強引用將對象釋放掉后,弱引用會自動的被賦值為nil,即弱引用會自動的指向nil。

Strong 強引用,舉個例子:

1 id __strong test0 = [[NSObject alloc] init]; /* 設為對象A*
2
3 id __strong test1 = [[NSObject alloc] init];/*設為對象B*/

test0 和 test1 都是強引用,test0是對象A的持有者,就是擁有A,test1是對象B的持有者,就是擁有對象B,若:

test1 = test0;/*對象A的持有者就變成了test1*/

這樣對象B就沒有了持有者,沒有持有者的對象會被ARC回收,就是釋放,這樣:

test1持有對象A,test0也持有對象A。

 

weak 弱引用,主要作用是用來防治循環引用出現內存泄漏的問題,它主要是弱引用,弱引用就是不持有對象,只是指向這個對象,舉個例子:

1 id __strong test0 = [[NSObject alloc] init]; /* 設為對象A*
2
3 id __strong test1 = [[NSObject alloc] init];/*設為對象B*
4
5 id __weak test2 = test0;/*test1持有對象A的弱引用*/

test0持有對象A的強引用,而test2持有對象A的弱引用,也就是說,test0還是持有A的,而test2弱引用了test0的對象A,並沒有持有對象A,當test2離開了作用域,對對象A的引用就會失去,當對象A被釋放掉之后,test2會被置為nil,並不會出現crash。若:

test1 = test0;/*test1強引用對象A*/

此時對象B因為沒有持有者就會被釋放。

 

再如:

 1 #import <Foundation/Foundation.h>
2
3 int main(int argc, const char * argv[]) {
4 @autoreleasepool {
5 id __weak obj0 = nil;
6 if (YES) {
7 id obj1 = [[NSObject alloc] init];  //默認為強引用,即為strong類型
8 obj0 = obj1;
9 NSLog(@"obj0: %@", obj0);
10 }
11 NSLog(@"obj0: %@", obj0);
12 }
13 return 0;
14 }
15
16 /*
17 * 輸出結果
18 * obj0: <NSObject: 0x1003066c0>
19 * obj0: (null)
20 *
21 * 因為obj1生成的默認的為強引用(__strong),在超出if的作用域之后,obj1所持有的對象被釋放,
22 * obj0為弱引用,所以obj0不持有對象,在obj1對象釋放后,obj0自動的被賦值為nil
23 * 弱引用的特性是,不持有對象,即便是寫成id __weak obj1 = [[NSObject alloc] init];
24 * 此代碼系統會給與警告,因為這里obj1被聲明成弱引用,那么在賦值之后,alloc出來的對象會被立即釋放。
25 */

 

 

 

 

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



內存管理機制 內存管理機制 Android 內存管理機制 Python的內存管理機制 android內存管理機制(一) JVM內存管理機制 Python內存管理機制 Qt 內存管理機制 Spark內存管理機制 Java的內存管理機制
 
粤ICP备14056181号  © 2014-2020 ITdaan.com