1、Objective-C記憶體管理簡介:
Objective-C需要自己考慮記憶體的管理,對於從Java, C#等語言轉向Objective-C平台的程式員新手來說,這是個很大的挑戰。幸運的是,如果熟悉了Objective-C的記憶體管理機制,手工管理記憶體也沒有那麼可怕。 Objective-C的記憶體管理介於C/C++和Java C#直接,不像C/C++語言記憶體管理全部需要程式員一手包辦,也不像Java C#語言有那麼完備的記憶體記憶體回收行程。(Objective-C 2.0有GC機制,不過不支援IOS)。那他是怎麼管理記憶體的呢?通過引用計數進行管理的。PS:在iOS
5後增加了Automatic Reference Counting(ARC 自動引用計數)特性,這樣程式員不需要自己操心管理記憶體了,ARC和GC不一樣,ARC是編譯器的行為。ARC後面再講。不過熟悉Objective-C的記憶體管理機制是非常必要的。
2、記憶體管理原理:
Objective-C記憶體管理模型是基於對象的所有權。如果你擁有這個對象,那麼你就有責任去釋放它。一個對象可以有多個擁有者。如果這個對象的擁有和為0時,系統將自動釋放這個對象。對象的所有權和釋放有四個原則:
- 任何你建立的對象你都獲得其所有權。(包括 alloc ,new ,copy等關鍵字獲得的對象)
- 通過retain獲得對象的所有權
- 如果你不需要一個對象了,你必須釋放所有權
- 你不能釋放你沒有所有權的對象
引用計數(retainCount)是Objective-C對象引用的唯一依據。調用執行個體管理的release方法後,此屬性減1,減到為零時對象的dealloc方法被自動調用,進行記憶體回收操作,也就是說我們永不該手動調用對象的dealloc方法。圖片來自蘋果官網。3、樣本:環境是在不選擇ARC的環境下建立Person類,使他繼承與NSObject,在.m檔案中實現dealloc方法:
- (void) dealloc { NSLog (@"dealloc called. Bye Bye."); [super dealloc]; }
在引用計數為0時,這個方法就會被調用,證明這個對象被銷毀。建立一個對象,列印它的引用計數
Person *person = [[Person alloc] init]; NSLog(@"對象person的retainCount: %d", [person retainCount]);
對象person的retainCount: 1
我們增加1
Person *person = [[Person alloc] init]; NSLog(@"對象person的retainCount: %d",[person retainCount] ); [person retain]; NSLog(@"對象person的retainCount: %d", [person retainCount]);
列印結果:
對象person的retainCount: 1
對象person的retainCount: 2
和傳說的一樣,retainCount增加了。可以有在release時,減少到1時就不再減 了
Person *person = [[Person alloc] init]; NSLog(@"對象person的retainCount: %d",[person retainCount] ); [person retain]; NSLog(@"對象person的retainCount: %d", [person retainCount]); [person release]; [person release]; NSLog(@"對象person的retainCount: %d", [person retainCount]);
這個代碼最後列印出來的retainCount是0嗎?列印結果:
2012-07-05 16:05:29.830 ObjectiveCTest[2847:f803] 對象person的retainCount: 12012-07-05 16:05:29.831 ObjectiveCTest[2847:f803] 對象person的retainCount: 22012-07-05 16:05:29.831 ObjectiveCTest[2847:f803] dealloc called. Bye Bye.2012-07-05 16:05:29.832 ObjectiveCTest[2847:f803] 對象person的retainCount: 1
震驚了,第一次release 時retainCount減1了,再release , d對象的dealloc called了,但是retainCount 還是1.在stackoverflow.com的查了一下,有人說這個retainCount沒什麼用。。。。可以事實的確如retainCount是1,對象被幹掉了。有人說,要把person
= nil。這樣retainCount就是0了。試了下,nil的 retainlCount永遠是0.這個賦值沒有意義。
4、NSAutoreleasePool自動釋放記憶體
如果僅僅是建立,釋放,這樣對應,就很好理解。但是大多數人不理解的是自動釋放記憶體這個地方,感覺琢磨不透,但其實原理也很簡單。
C/C++編程時有個很重要的對記憶體管理的原則:誰建立誰銷毀。但是這個原則在有些情況下卻無法遵守:比如讓一個普通函數返回一塊記憶體地區。函數調用者必須在函數調用完畢後自己負責銷毀這塊記憶體,而在Objective-C的自動記憶體釋放的機制下,就不用那麼煩惱了。
先看看最經典的程式入口程式,也用到自動釋放。
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];int retVal = UIApplicationMain(argc, argv, nil, nil);[pool release];
我們先把pool看成一個普通對象,先是alloc,pool的retainCount為1。
第三句release,retainCount為0,自動調用它的dealloc方法。它和任何其它普通對象沒 任何區別。
神奇的地方在哪裡?
NSAutoreleasePool內部包含一個數組(NSMutableArray),用來儲存聲明為autorelease的所有對象。如果一個對象聲明為autorelease,系統所做的工作就是把這個對象加入到這個數組中去。NSAutoreleasePool自身在銷毀的時候,會遍曆一遍這個數組,release數組中的每個成員。如果此時數組中成員的retain count為1,那麼release之後,retain count為0,
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; Person *person = [[Person alloc] init]; NSLog(@"對象person的retainCount: %d",[person retainCount] ); [person autorelease]; NSLog(@"到這裡,person還沒被釋放"); [pool release];
列印結果:
2012-07-05 16:34:38.823 ObjectiveCTest[3045:f803] 對象person的retainCount: 12012-07-05 16:34:38.823 ObjectiveCTest[3045:f803] 到這裡,person還沒被釋放2012-07-05 16:34:38.824 ObjectiveCTest[3045:f803] dealloc called. Bye Bye.
在調用pool release的時候,person才被釋放。這就是自動釋放的神奇的地方,這樣就可以建立對象
著作權聲明:本文由http://blog.csdn.net/totogo2010/原創,歡迎轉載分享。請尊重作者勞動,轉載時保留該聲明和作者部落格連結,謝謝!