1. 程式人生 > >[黑馬程式設計師][OC]記憶體管理

[黑馬程式設計師][OC]記憶體管理

一、記憶體管理的基本原理

1.什麼是記憶體管理

移動裝置的記憶體極其有限,每個app所能佔用的記憶體是有限制的,當app所佔用的記憶體較多時,系統會發出記憶體警告,這時得回收

一些不需要再使用的記憶體空間。比如回收一些不需要使用的物件、變數等。管理範圍:任何繼承了NSObject的物件,對其他基本數

據型別(int、char、float、double、struct、enum等)無效。

2.引用計數器

1>每個OC物件都有自己的引用計數器,是一個整數,表示“物件被引用的次數”,即有多少人正在使用這個OC物件;

2>每個OC物件內部專門有4個位元組的儲存空間來儲存引用計數器;

3.引用計數器的作用

1>當使用alloc、new或者copy建立一個新物件時,新物件的引用計數器預設就是1;

2>當一個物件的引用計數器值為0時,物件佔用的記憶體就會被系統回收。換句話說,如果物件的計數器不為0,那麼在整個程式執行

過程,它佔用的記憶體就不可能被回收,除非整個程式已經退出

4. 引用計數器的操作

1>給物件傳送一條retain訊息,可以使引用計數器值+1(retain方法返回物件本身);

2>給物件傳送一條release訊息,可以使引用計數器值-1;

3>可以給物件傳送retainCount訊息獲得當前的引用計數器值;

5. 物件的銷燬

1>當一個物件的引用計數器值為0時,那麼它將被銷燬,其佔用的記憶體被系統回收;

2>當一個物件被銷燬時,系統會自動向物件傳送一條dealloc訊息;

3>一般會重寫dealloc方法,在這裡釋放相關資源,dealloc就像物件的遺言;

4>一旦重寫了dealloc方法,就必須呼叫[super dealloc],並且放在最後面呼叫;

5>不要直接呼叫dealloc方法;

6>一旦物件被回收了,它佔用的記憶體就不再可用,堅持使用會導致程式崩潰(野指標錯誤);

程式碼示例:

1.Car.h

#import <Foundation/Foundation.h>

@interface Car : NSObject
{
    int _speed;
}

- (void)setSpeed:(int)speed;
- (int)speed;
@end

2.Car.m

#import "Car.h"

@implementation Car
- (void)setSpeed:(int)speed
{
    _speed = speed;
}
- (int)speed
{
    return _speed;
}


- (void)dealloc
{   
    NSLog(@"速度為%d的Car物件被回收了", _speed);
    
    [super dealloc];
}

@end

3.Person.h

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

@interface Person : NSObject
{
    Car *_car;
    int _age;
}

- (void)setAge:(int)age;
- (int)age;

- (void)setCar:(Car *)car;
- (Car *)car;

@end

4.Person.m

#import "Person.h"

@implementation Person
- (void)setCar:(Car *)car
{
    if (car != _car)
    {
        // 對當前正在使用的車(舊車)做一次release
        [_car release];
        
        // 對新車做一次retain操作
        _car = [car retain];
    }
}
- (Car *)car
{
    return _car;
}

- (void)setAge:(int)age
{ // 基本資料型別不需要管理記憶體
    _age = age;
}
- (int)age
{
    return _age;
}

- (void)dealloc
{
    // 當人不在了,代表不用車了
    // 對車做一次release操作
    [_car release];
    
    NSLog(@"%d歲的Person物件被回收了", _age);
    
    [super dealloc];
}

@end

5.main.m

int main()
{
    // 物件p的引用計數器為:1
    Person *p = [[Person alloc] init];
    p.age = 20;
    
    // 物件c的引用計數器為:1


    Car *c = [[Car alloc] init];
    c.speed = 250;
    
    // 物件c的引用計數器為:2
    p.car = c;
    
    //物件c的引用計數器為:1
    [c release];
    
    //物件p的引用計數器為:0;物件p被回收,呼叫物件p的dealloc方法,對車做一次release操作,這時c的引用計數器,也減為0,物件c也被回收。
    [p release]; 
    return 0;
}

二、記憶體管理原則

1.原則分析

1>只要還有人在用某個物件,那麼這個物件就不會被回收;

2>只要你想用這個物件,就讓物件的計數器+1;

3>當你不再使用這個物件時,就讓物件的計數器-1;

2. 誰建立,誰release

1>如果你通過alloc、new或[mutable]copy來建立一個物件,那麼你必須呼叫release或autorelease;

2>換句話說,不是你建立的,就不用你去[auto]release;

3. 誰retain,誰release

只要你呼叫了retain,無論這個物件是如何生成的,你都要呼叫release;

4. 總結

1>有始有終,有加就有減;

2>曾經讓物件的計數器+1,就必須在最後讓物件計數器-1;