------- android培訓、java培訓、期待與您交流!
=====================引用計數器開始====================
基本類型數據存放在棧中,對象存放在堆中
棧中的數據系統自動回收
堆空間中的數據動態分配,不能自動分配,容易引起內存泄露
需要給對象發送消息,讓它回收,即調用對象的回收方法
1.系統如何判斷對象是否需要回收
需要理解對象內部結構:
每一個OC對象內部都有一個 引用計數器 (即被引用的次數),4個字節存儲空間
當減爲0時,回收
剛創建時,爲1
2.引用計數器的作用
當使用alloc,new或者[mutable]copy創建一個新對象時,默認計數器爲1
如果對象計數器不爲0,他就不會被回收,一直在內存中
3.引用計數器的操作
>給對象發送一條retain消息,可以使對象計數器+1(retain方法返回對象本身)
>給對象發送一條release消息,可以使對象計數器-1
>retainCount返回引用計數器的值
4.引用計數器的銷燬
>當一個對象的引用計數器爲0時,他會被銷燬,所佔用的內存會被回收
>當一個對象被銷燬時,系統會自動向對象發送一條dealloc消息
>一般會重寫dealloc方法,並且一定要調用[super dealloc],並且放在最後在這裏釋放相關資源
重寫dealloc方法來看程序是否被回收:
- (void)dealloc{
NSLog(@"對象被回收");
//super的dealloc一定要調用,而且要放到最後面
[super dealloc];
}
//調用:
原則:一調用alloc,就得調用一次release;一調用retain,就得調用一次release
int main(){
Person *p = [[Person alloc] init];
NSUInteger c = [p retainCount];//結果是1
//[p release];//計數器-1,爲0,在main函數還沒有結束就已經回收了對象內存
[p retain];//返回對象本身,計數器+2
return 0;
}
殭屍對象:已經被回收內存的對象
野指針:指向殭屍對象(不可用內存)的指針
1.此時會報錯:EXC_BAD_ACCESS------由於訪問了一塊壞的內存(已經被回收,不可被訪問的內存)
2.如果繼續使用對象調用任何方法(包括[p retain]),則會報錯:-[Person setAge:]: message sent to deallocated instance 0x100109a10----會出現閃退
如何避免:設置p=nil 變爲空指針,p指針就不存在,給空指針發送消息就不會報錯(即p調用方法)
OC中不會報空指針錯誤
int main(){
Person *p = [[Person alloc] init]; //1
[p retain]; //2
[p release]; //1
[p release]; //0 被回收,此時Person對象成爲殭屍對象,指針p稱爲野指針
[p release];//會報錯,
return 0 ;
}
=====================引用計數器完====================
====================多個對象內存管理開始====================
當你想使用某個對象,應該對這個對象的計數器+1,不使用的時候-1
>誰創建 誰release
>誰retain 誰release
舉個栗子:
Book.h中:
#import <Foundation/Foundation.h>
@interface Book : NSObject
//@property int price;//價格 由於涉及內存,不用property,因爲它會屏蔽內存管理細節
{
int _price;
}
- (void)setPrice:(int)price;
- (int)price;
@end
Book.m中:
#import "Book.h"
@implementation Book
- (void)setPrice:(int)price
{
_price = price;
}
- (int)price
{
return _price;
}
//需要重寫dealloc方法
- (void)dealloc
{
NSLog(@"Book對象被回收");
[super dealloc];
}
@end
Person.h中:
#import <Foundation/Foundation.h>
#import "Book.h"
@interface Person : NSObject
{
Book *_book;
}
- (void)setBook:(Book *)book;
- (Book *)book;
@end
Person.m中:
#import "Person.h"
@implementation Person
- (void)setBook:(Book *)book
{
_book=[book retain];
}
- (Book *)book;
{
return _book;
}
//需要重寫dealloc方法
- (void)dealloc
{
[_book release];//人掛了,當然書就不用了
NSLog(@"Person對象被回收");
[super dealloc];
}
@end
主函數:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Book.h"
int main(){
Book *b = [[Book alloc] init];//書兩種情況需要被release:1.換一本書 2.人掛了 所以在這兩種情況都要加release
Person *p1 = [[Person alloc] init];
//p1想佔用b一次
[p1 setBook:b];//去Person.m中讓book retain一次
[b release];//b不想用Book對象了,就應該讓指針變空
b=nil;
[p1 release];//p1不用了,就用p1把對象人中的計數器-1,這時候計數器爲0,對象人就掛了,那人
p1=nil;
return 0;
}
====================多個對象內存管理完====================