天天看點

IOS開發基礎Object-C(07)—OC記憶體管理(1)-retain和release

前面我們已經說過,OC不同于Java的地方就是沒有垃圾回收機制,在記憶體管理這塊,cocoa引入了一種稱為引用計數(reference counting)的技術,有時也叫保留計數,每個對象有一個與之對關聯的整數,稱作它的引用計數器或保留計數器.當某段代碼要通路一個對象的時候,該代碼将該對象的保留計數值加1,表示”我要通路該對象”,當這段代碼結束對象通路時,将對象的保留計數值減1,表示它不再通路該對象,當保留計數值為0時,表示不再有代碼通路對象了,對象被銷毀,其占用的記憶體被系統回收。

我來簡單說一下原理:

1、每個對象内部都儲存了一個與之關聯的整數,稱之為引用計數器,當使用alloc、new或者copy建立一個對象時,對象的引用計數器被設定為1;

2、給對象發送一個retain消息(調用retain方法),可以使計數器+1;

3、給對象發送一個release消息(調用release方法)或者autorelease消息,可以使計數器-1;

4、當一個對象的引用計數為0時,那麼他将被銷毀,其占用的記憶體被系統回收,OC也會自動向對象發送一條dealloc消息,一般會重寫dealloc方法,在這裡釋放相關資源,一定不要直接調用dealloc方法。

5、發送retainCount消息獲得目前的引用計數器的值。

注:我們這裡說的發送消息就是調用方法

- (id)retain; // 計數器+1

- (void)release; //計數器-1

- (id)autorelease;//計數器-1

- (unsigned)retainCount;//獲得目前引用計數器的值

在這裡大家就會疑惑了,怎麼的對象才需要我們管理記憶體呢?可以這麼說,任何繼承了NSObject的對象都需要管理記憶體。基本資料類型,像int ,float,double,int類型的指針數組什麼的都不需要管理記憶體。

我們來看一下例子依照慣例,我們還是來建立一個類:

Student.h

#import<Foundation/Foundation.h>
@interface Student :NSObject
@property int age; //聲明一個getter方法、setter方法
@end
           

Student.m

#import "Student.h"
@implementation Student

@synthesize age=_age; //在xcode4.5環境下可以省略

//驗證對象有沒有被回收
-(void)dealloc
{
    NSLog(@"%@被銷毀了",self);//驗證對象有沒有被回收
    [super dealloc];//一定要到調用super的dealloc方法,而且最好是在最後調用
}
@end
           

我們在main.m中測試一下

#import<Foundation/Foundation.h>
#import"Student.h"

int main(int argc,const char *argv[])
{
    @autoreleasepool{
         Student *stu=[[Student alloc]init];//調用了alloc方法,計數器為1
         [stu release];//釋放,計數器為0;
        }
    return ;
}
           

在前邊我們有提到,在銷毀對象的時候,OC也會自動向對象發送一條dealloc消息,一般會重寫dealloc方法,在這裡釋放相關資源,一定不要直接調用dealloc方法。是以我們用dealloc方法來驗證對象是否被銷毀。

如果對象被回收以後(retainCount=0),再發送一條release消息,就會發生野指針錯誤。

#import<Foundation/Foundation.h>
#import"Student.h"

int main(int argc,const char *argv[])
{
    @autoreleasepool{
         Student *stu=[[Student alloc]init];//調用了alloc方法,計數器為1
         [stu release];//釋放,計數器為0

         [stu release];//計數器為0,再次釋放則會發生野指針錯誤,也就是說通路了你不該通路的記憶體
        }
    return ;
}
           

autorelease的實作

還有一種情況,如果方法名并不以alloc、new、copy開頭,比如:

+ (NSArray *)array  
{  
    return [[NSArray alloc] init] autorelease];  
}  
           

程式内部調用了alloc,就需要調用release來釋放,是以我們采用了一種自動釋放機制autorelease,其中具體原理先不深究,後面我會詳細講解。

記憶體管理原則:

1、誰建立,誰釋放(“誰污染,誰治理”),如果你通過alloc、new或者copy來建立一個對象,那麼你必須調用release或者autorelease來釋放,換句話說,不是你建立的,你就不用釋放

2、一般來說,除了alloc、new或者copy之外的方法建立的對象,都被聲明了autorelease

3、誰retain,誰release,無論這個對象是怎樣生成的

視訊連結

http://pan.baidu.com/s/1ntMpRQT

繼續閱讀