Object C學習筆記4-內存管理

  Object-C的內存管理和.NET有些不同,.NET的內存回收機制是使用GC自動處理回收,而Object-C本質上仍是C語言,因此不少時候仍是須要手動去管理內存回收。數組

  1. Object-C生成一個對象ide

    Engine *en=[[Engine alloc] init];spa

    [en dealloc];3d

    Object-C對象生成分配空間在堆上,須要使用指針來指向其引用。前面也說到了,Object-C中得對象其實就是C中的指針。指針

  2. 對象初始化以及銷燬方法code

    +(id) alloc; 注意這裏的alloc是一個類方法,調用alloc方法以後會在內存中分配一塊空間,而且引用計數會設置爲1對象

    +(id) init; 調用init方法表示初始化對象blog

    -(void) dealloc; 這裏注意一下dealloc不是一個類方法,而是一個實例方法。dealloc 方法用於銷燬對象,當引用計數爲0的時候系統會自動調用dealloc方法銷燬對象內存

    -(void) release; 調用這個方法用於釋放對象的引用,引用計數會-1資源

    -(void) retain ;調用這個方法用於將引用計數+1

    - (NSUInteger)retainCount; 用於獲取一個對象當前被多少對象擁有

  3. 叫苦連天的內存泄露

    實例一: 

Engine *en=[[Engine alloc] init];
Engine *en2=en;
[en print];
[en dealloc];
[en2 print];
[en2 dealloc];
實例一 代碼

    [en print]; 這段代碼可以正確的輸出數據;[en2 print] 和 [en2 dealloc] 方法則不能正常執行。由於en,en2 指針都指向了同一個對象引用,而[en dealloc]調用釋放了這個對象。當en2 調用print 和 dealloc的時候,該對象已經不存在了。

    實例二:

Engine *en=[[Engine alloc] init];
Engine *en2=en;
[en print];
[en release];
[en2 print];
[en2 release];
[en release];
實例二 代碼

    [en print]這段代碼可以正常的輸出數據,而[en2 print]仍然不能正常執行。爲何?當調用[[Engine alloc ] init] 的時候,en 指針指向這個對象,這個時候retainCount=1 。

    Engine *en2=en 這個時候將指針en2也指向這個對象,retainCount=1;

    當en調用release方法的時候,retainCount 數量-1,retainCount=0; 這個時候系統會自動調用dealloc方法,自動回收對象。因此當下面再次調用的時候則不能正常執行。

    實例三:

Engine *en=[[Engine alloc] init];
Engine *en2=en;
[en2 retain];
[en print];
[en release];
[en2 print];
[en2 release];
實例三 代碼

    這段代碼和上面一段代碼的區別在於調用了[en2 retain]. 在Object-C中retainCount不會自動增長,須要調用retain纔會增長。因此當調用[en2 retain]以後retainCount=2. 即便後面調用了[en release],retainCount仍然爲1,對象不會去銷燬。因此下面會正常執行。若是不調用[en2 release]那麼retainCount會始終等於1,對象不會獲得釋放就會發生內存泄露。

 

  4. 內存自動回收處理

   上面的處理的確有點太麻煩了,內存管理簡直就是噩夢。只要稍微不注意就內存泄露了。如今還有更好的一種方式解決以上問題,那就是autorelease pool(自動釋放對象池)。使用自動釋放對象池,在某些狀況一下能夠不用手工去處理對象內存的釋放,貌似和.NET中的垃圾回收機制有點相似了,可是咱們不要徹底的依賴與它,這和自動管理內存仍是有必定差距的。

Engine *en=[[[Engine alloc] int] autorelease];
Engine *en2=en;
[en2 retain];
[en print];
//[en release];
[en2 print];
[en2 release];
自動釋放對象池

  看到上面的代碼,en 並無顯示去調用release方法。而autorelase pool 就是有這樣的一個好處。

 

  5. 自動回收原理簡介

  要使用自動回收咱們必須手工建立自動釋放對象池,NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  NSAutoreleasePool內部包含一個數組(NSMutableArray),用來保存聲明爲autorelease的全部對象。若是一個對象聲明爲autorelease,系統所作的工做就是把這個對象加入到這個數組中去。當NSAutoreleasePool自身釋放的時候,會遍歷數組中的全部對象,而且調用release方法。若是對象的retainCount=0 那麼系統會釋放這些對象,若是retainCount>0,則會內存泄露。

  在某些狀況下,NSAutoreleasePool 調用的銷燬方法比較遲,這個時候會佔用大量的內存,咱們也能夠使用內嵌的方式,建立多個NSAutorelease的實例,讓佔用的資源立馬釋放掉。

相關文章
相關標籤/搜索