码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-03-11 23:25:11      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:

手动内存管理

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

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

  • alloc
  • new
  • copy
  • mutableCopy

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

  • retain :保留对象,对象的引用计数器+1。
  • release : 释放对象,对象引用计数器-1。
  • retainCount : 获取对象当前的引用数。
  • autorelease : 将对象托管到自动释放池。
  • dealloc : 对象释放之前调用的方法,由系统自动调用,不能主观调用。

直赋值接指针和retain的区别

  1. Person *p = [[Person alloc] init];
  2. //指针赋值并不会让对象的引用计数器+1
  3. Person *p2 = p ;
  4. // 输出p2 retainCount = 1, p retainCount = 1
  5. NSLog(@"p2 retainCount = %lu , p retainCount = %lu",[p2 retainCount],[p retainCount]) ;
  6. // retain 会让引用计数器+1
  7. Person *p3 = [p retain] ;
  8. // 输出2,2,2
  9. NSLog(@"p3 retainCount = %lu,p2 retainCount = %lu , p retainCount = %lu",[p3 retainCount],[p2 retainCount],[p retainCount]) ;
  10. // 释放对象,谁污染的谁治理
  11. [p release] ; // 引用数量变为1
  12. // 释放对象
  13. [p3 release] ; // 引用数量变为0 , 调用对象dealloc方法
  14. //[p2 release] ; // 这句报错,因为所指向的对象已经被释放掉了
  • 直接指针赋值并不会让引用计数器+1
  • retain(保留)会使引用计数器 +1 .

AutoReleasePool 自动释放池

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

  1. // 创建自动释放池
  2. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  3. Person * p = [[Person alloc] init];
  4. // 添加到自动释放池
  5. [p autorelease] ;
  6. // 自动释放,其中托管的对象也会被释放
  7. [pool release] ;

AutoReleasePool 和 @autoreleasepool {}

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

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

多个NSAutoreleasePool嵌套

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

  1. NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];
  2. Person *p1 = [Person new];
  3. // 被托管在pool1 中
  4. [p1 autorelease] ;
  5. NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];
  6. Person *p2 = [Person new];
  7. // 被托管 在 pool2中
  8. [p2 autorelease];
  9. [pool2 release] ;
  10. [pool1 release] ;

事件循环和内存分配

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

  1. -(void) onClick {
  2. // 在事件方法结束后data 所指向的内存块默认会被清理,为了保留下来data 对象,我们使用了retain关键字.
  3. data = [[NSMutableArray array] retain] ;
  4. }

属性对象的释放问题。

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

  1. @implementation Person
  2. {
  3. // 是指针 , 存在于内存中。
  4. NSObject *obj ;
  5. }
  6. // 重写父类的dealloc 方法
  7. - (void)dealloc
  8. {
  9. NSLog(@"test") ;
  10. // 释放属性
  11. [obj release] ;
  12. // 注意:必须写上这一句,释放父类的资源
  13. [super dealloc] ;
  14. }
  15. @end
  1. // 引入Person 类
  2. #import "Person.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. Person *p = [Person new] ;
  7. // p release 的时候会调用dealloc 方法,释放Person类自身的属性.
  8. [p release] ;
  9. }
  10. return 0;
  11. }

属性的参数 : retain 和 assign

@property(assign) NSObject *obj ;

retain

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

  1. -(void)setObjA:(ClassA *)a
  2. {
  3. If(objA != a)
  4. {
  5. [objA release];
  6. objA = [a retain];//对象的retain count 加1
  7. }
  8. }

assign (默认)

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

  1. -(void)setObjA:(ClassA *)a
  2. {
  3. objA = a;
  4. }

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

标签:

原文地址:http://www.cnblogs.com/mrwu/p/4331161.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!