[黑馬程式設計師][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;