您的位置:首页 > 其它

手动内存管理和自动释放池

2015-03-11 22:33 225 查看

手动内存管理

在进行内存管理的时候要注意内存管理的准则:谁开辟内存,谁释放内存(谁污染的谁治理) 。
开辟内存之后,对象的引用计数为1,只有继承自NSObject的对象才有内促管理的概念, 当对象引用计数为0的时候对象的内存会被清理。

下列关键字会开辟内存,对象引用计数器+1

alloc

new

copy

mutableCopy

下列是内存管理的相关方法。

retain :保留对象,对象的引用计数器+1。

release : 释放对象,对象引用计数器-1。

retainCount : 获取对象当前的引用数。

autorelease : 将对象托管到自动释放池。

dealloc : 对象释放之前调用的方法,由系统自动调用,不能主观调用。

直赋值接指针和retain的区别

Person *p = [[Person alloc] init];

//指针赋值并不会让对象的引用计数器+1

Person *p2 = p ;

// 输出p2 retainCount = 1, p retainCount = 1

NSLog(@"p2 retainCount = %lu , p retainCount = %lu",[p2 retainCount],[p retainCount]) ;


// retain 会让引用计数器+1

Person *p3 = [p retain] ;

// 输出2,2,2

NSLog(@"p3 retainCount = %lu,p2 retainCount = %lu , p retainCount = %lu",[p3 retainCount],[p2 retainCount],[p retainCount]) ;

// 释放对象,谁污染的谁治理

[p release] ; // 引用数量变为1

// 释放对象

[p3 release] ; // 引用数量变为0 , 调用对象dealloc方法

//[p2 release] ; // 这句报错,因为所指向的对象已经被释放掉了

[/code]
直接指针赋值并不会让引用计数器+1

retain(保留)会使引用计数器 +1 .

AutoReleasePool 自动释放池

在开发过程中,某些对象可能并不能立马释放掉,可以暂时将这个对象托管进当前上下文中的自动释放池,以便最后统一释放。

// 创建自动释放池

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Person * p = [[Person alloc] init];

// 添加到自动释放池

[p autorelease] ;

// 自动释放,其中托管的对象也会被释放

[pool release] ;

[/code]

AutoReleasePool 和 @autoreleasepool {}

@autoreleasepool {} 是NSAutoreleasePool 的另一种写法,'{}' 内的代码就是在一个NSAutoreleasePool 中。

@autoreleasepool{

} // 相当于系统自动创建NSAutoreleasePool 自动在结尾处让这个pool release.

[/code]

多个NSAutoreleasePool嵌套

程序中可以嵌套多个自动释放池,autorelease 的对象托管在对象代码所在的释放池。

NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];


Person *p1 = [Person new];


// 被托管在pool1 中

[p1 autorelease] ;


NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];


Person *p2 = [Person new];

// 被托管 在 pool2中

[p2 autorelease];


[pool2 release] ;



[pool1 release] ;

[/code]

事件循环和内存分配

在开发IOS程序的时候,处理一个按钮的单击事件会调用单击响应的方法,系统会创建一个新的自动释放池给这个响应方法使用,当这个事件处理方法结束后系统就会release创建的自动释放池,由于事件可以多次循环发生,每一次发生系统都会创建一个针对于当前事件的自动释放池,事件处理完毕后释放这个自动释放池。我们可以使用retain来保存对象不被事件自动创建的自动释放池清理.
系统API中的对象大多是被自动释放池托管的,所以我们无需关心这些对象的释放。


-(void) onClick {

// 在事件方法结束后data 所指向的内存块默认会被清理,为了保留下来data 对象,我们使用了retain关键字.

data = [[NSMutableArray array] retain] ;

}

[/code]

属性对象的释放问题。

当一个累的属性是另一个对象的指针时,我们可以重写dealloc方法来释放属性对象。

@implementation Person

{

// 是指针 , 存在于内存中。

NSObject *obj ;

}

// 重写父类的dealloc 方法

- (void)dealloc

{

NSLog(@"test") ;

// 释放属性

[obj release] ;

// 注意:必须写上这一句,释放父类的资源

[super dealloc] ;

}

@end

[/code]
// 引入Person 类

#import "Person.h"

int main(int argc, const char * argv[])

{

@autoreleasepool {

Person *p = [Person new] ;

// p release 的时候会调用dealloc 方法,释放Person类自身的属性.

[p release] ;

}

return 0;

}

[/code]

属性的参数 : retain 和 assign

@property(assign) NSObject *obj ;

retain

retain 属性合成的setter 保留一下再赋值,引用计数器+1

-(void)setObjA:(ClassA  *)a

{

If(objA != a)

{

[objA  release];

objA  =  [a retain];//对象的retain count 加1

}

}

[/code]

assign (默认)

assign 属性合成的setter直接赋值,引用计数器不会+1

-(void)setObjA:(ClassA  *)a

{

objA  =  a;

}

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: