Object-C 學習筆記(十)---內存管理MRC

內存管理


MRC——手動管理內存

ARC——自動管理內存


MRC

OC採用“引用計數”(retainCount)方式管理對象佔用的內存

1.      使用alloc爲對象分配內存;使用dealloc釋放對象所佔用的內存。

2.      使用alloc、new或者copy構造對象是,對象的retainCount爲1.

3.      調用對象的retain方法可以增加1 retainCount

4.      調用對象的release方法可以減少1 retainCount

5.      當對象的retainCount爲0時,dealloc會自動調用,釋放對象內存;否則分配的內存講被一直佔用。

6.      所有對象可以使用retainCount屬性查看當前的計數器值。

 

 

例子:

NSString *dadyCar = [[NSStringalloc]initWithFormat:@”Car”];// dadyCar擁有對象所有權retainCount+1

NSString *mumCar = [dadyCar retain];// mumCar擁有對象所有權,retainCount+1

 

NSString *sonCar = [mumCar retain];// sonCar擁有對象所有權,retainCount+1

 

NSString * friendCar = sonCar;// friendCar不擁有對象的所有權,只是簡單指向對象內存空間,retainCount不會發生變化

 

[dadyCar release];// retainCount-1

[mumCar release];// retainCount-1

[sonCar release];// retainCount-1

注意:

         如果所有擁有對象的引用都釋放了對象的所有權(retainCount=0),那麼friendCar就變成了“野指針”,因爲對象已經不存在,不能再調用對象的資源。



@property(retain,nonatomic)Strdent

一個類中,如果這個類有屬性聲明retain或者copy的屬性,那麼我們需要再這個類的dealloc方法裏面釋放這個屬性。

 

dealloc方法在對象引用計數爲0是自動調用。

主要用於適當自身所佔用的資源。永遠不要手動調用dealloc,應由系統自動調用。

 

真正釋放對象內存空間的方位爲:dealloc

當一個對象引用計數變成1時,再調用release的時候,其release就會自動調用系統的dealloc方法去釋放對象所佔的空間。

 

一般在類中需要overwrite覆蓋/重寫/複寫dealloc方法,進行屬性控制。

-(void)dealloc//相當於C++的析構方法

{

         //釋放子類的引用

         [super dealloc];//調用父類的dealloc,釋放父類

}

 

內存釋放原則一:

       對象分配內存,並應在使用後,調用release釋放內存。

凡是出現retain alloc copy的地方,都應該出現release與之匹配調用。

 

內存釋放原則二:

         內存無法確定釋放時間是,可以使用autorelease向最近池註冊。

         有池決定釋放時間

         使用便利構造器獲得的對象,都應該是autorelease的。

 

Autorelease://自動釋放

——延時釋放對象內存。

對於每一個Runloop, 系統會隱式創建一個Autoreleasepool,這樣所有的release pool會構成一個象CallStack一樣的一個棧式結構,在每一個Runloop結束時,當前棧頂的Autorelease pool會被銷燬,這樣這個pool裏的每個Object會被release。

例子:除了大括號之後,會自動release

 

(1)     當創建的對象未來某個時候銷燬是,可以使用對象的autorelease。

(2)     對象講所有管理權交給最近的NSautoreleasePool對象,並由其全權釋放。

 

Autoreleasepool://自動釋放池

         對象使用autorelease釋放的會放進Autoreleasepool,系統自動釋放。


例子:

//
//  People.h
//  Memory
//
//  Created by 5016 on 13-12-4.
//  Copyright (c) 2013年 dradon. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface People : NSObject

//成員屬性
@property(retain,nonatomic)NSString* name;
@property(assign,nonatomic)NSInteger age;

-(People *)initWithName:(NSString*) name andAge:(NSInteger) age;

+(People *)PeopleWithName:(NSString*) name andAge:(NSInteger) age;

-(void)toString;


@end

//
//  People.m
//  Memory
//
//  Created by 5016 on 13-12-4.
//  Copyright (c) 2013年 dradon. All rights reserved.
//

#import "People.h"

@implementation People

@synthesize name=_name,age=_age;

-(People *)initWithName:(NSString*) name andAge:(NSInteger) age
{
    if(self = [super init])
    {
        _name = name;
        _age = age;
    }
    return self;
}

//便利構造器
+(People *)PeopleWithName:(NSString*) name andAge:(NSInteger) age
{
    People *person = [[People alloc] initWithName:name andAge:age];
    
    return [person autorelease];//向自動釋放池註冊
}


-(void)toString
{
    NSLog(@"我的名字是%@,今年%ld歲.",_name,_age);
}

//重寫(overwirte)父類方法
-(void)dealloc//用來釋放對象的方法,相當於C++裏面的析構方法
{
    NSLog(@"這個對象被完全釋放");
    self.name = nil;//等價於[_name release]或者[self.name release];
    [super dealloc];
}

@end

//
//  main.m
//  Memory
//
//  Created by 5016 on 13-12-4.
//  Copyright (c) 2013年 dradon. All rights reserved.
//

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

int main(int argc, const char * argv[])
{
     NSLog(@"|-----------使用alloc開闢對象堆內存空間按-----------------|");
    People *person1 = [[People alloc]initWithName:@"DRAGON" andAge:23];//alloc開闢對象 +1
    [person1 toString];
    NSLog(@"person1的引用計數是:%ld",[person1 retainCount]);
    [person1 retain];//+1 = 2
    NSLog(@"person1的引用計數是:%ld",[person1 retainCount]);
    [person1 release];//-1 = 1 ;這裏對象已經釋放一次,引用計數爲1
     NSLog(@"person1的引用計數是:%ld",[person1 retainCount]);
    [person1 release];//-1 = 0 ;這裏對象再釋放一次,引用計數爲1-1,系統自動調用dealloc
    NSLog(@"person1的引用計數是:%ld",[person1 retainCount]);
    //[person1 release];//再調用一次,則是過度釋放,會出現異常
    
    NSLog(@"|-----------使用便利構造器-----------------|");
    @autoreleasepool {//使用自動釋放池進行釋放,因爲程序結束後會釋放
        People *person = [People PeopleWithName:@"dragon" andAge:20];
        [person toString];//使用便利構造器 不需要使用release
    }

    return 0;
}

運行結果:



相信到了這裏大家會基本理解內存管理.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章