------- 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;
}
==================== 多个对象内存管理完 ====================