Objective-c自学笔记(5)-自动释放池
来源:互联网 发布:红叶知弦h同人 编辑:程序博客网 时间:2024/05/22 12:04
解决的问题
每一个东西的产生都是在实际生活迫切需要这样的东西后,人们通过思考发明创造某些东西用以解决这个问题。那么自动释放池用来解决什么问题?请看下面的例子:
对于一些有返回值的消息(方法),它返回的对象要交给谁来释放其内存,比如NSObject类中description消息
-(NSString*)description{ NSString *description; description = [[NSString alloc]initWithFormat:@"hello world"]; return (description); }//description
这个时候description字符串的内存释放要交给谁?肯定不应该在description方法里面,这样的话,返回的对象指向的就是一个被释放的内存了。这肯定是不可行的。
那么如果让调用者来释放呢,那么就得像下面这样写:
RetainTracker *tracker = [RetainTracker new]; NSString *desc = [tracker description]; [desc release];
那么这样写有什么问题么?没什么问题,就是多了一行代码?有什么更好的方法,能只写一行代码就能达到自动释放的效果。既然有这个需求,那么肯定会有人试着去解决这个问题。
解决方法
苹果公司在Cocoa框架中有一个自动释放池的概念,在NSObject类中提供了一个叫做autorelease的方法。
-(id)autorelease{};//autorelease
该方法预先设定了一条会在未来某个时间发送的release消息, 返回的id代表接受这条消息的对象。当我们调用该对象的autorelease方法的时候,实际上是把该对象放到自动释放池,当自动释放池被销毁时,会向该池中的所有对象发送release消息。这个时候我们把description 方法修改成如下形式:
-(NSString*)description{ NSString *description; description = [[NSString alloc]initWithFormat:@"hello world"]; return ([description autorelease]); }//description
这个时候我们在调用的地方只需要一句话就做了内存释放的工作。不用在单独添加调用release方法的语句。
创建
我们上面说了那么多,都在说自动释放池可以帮我们解决掉对象自动释放的问题,但是这个自动释放池也不是自己就存在的,它需要我们自己来显示的创建。可以通过2种方式来创建自动释放池。
通过@autoreleasepool关键字
当你使用@autoreleasepool{}时,所有在花括号里的代码都会被放入这个池子中。但是任何在该花括号的变量都无法在括号外使用。
通过NSAutoreleasePool对象
该对象需要创建,在该对象创建语句和销毁语句的代码都相当于放入了自动释放池中。
NSAutoreleasePool *pool; pool = [NSAutoreleasePool new]; RetainTracker *tracker = [RetainTracker new]; NSString *desc = [tracker description]; [desc release]; // count: 1 [tracker retain]; // count: 2 NSLog (@"%d", [tracker retainCount]); [tracker retain]; // count: 3 NSLog (@"%d", [tracker retainCount]); [tracker release]; // count: 2 NSLog (@"%d", [tracker retainCount]); [tracker release]; // count: 1 NSLog (@"%d", [tracker retainCount]); [tracker retain]; // count 2 NSLog (@"%d", [tracker retainCount]); [tracker release]; // count 1 NSLog (@"%d", [tracker retainCount]); [tracker release]; // count: 0, dealloc it [pool release];
上面的代码就是一个自动释放池创建过程。
推荐
优先使用@autoreleasepool{}关键字的方式来创建自动释放池。
工作原理
那么自动释放池的工作原理到底是什么?下面用一个例子来讲解一下。
#import <Foundation/Foundation.h>@interface RetainTracker : NSObject@end // RetainTracker@implementation RetainTracker- (id) init{if (self = [super init]) {NSLog (@"init: Retain count of %d.", [self retainCount]);}return (self);} // init- (void) dealloc{NSLog (@"dealloc called. Bye Bye.");[super dealloc];} // dealloc@end // RetainTrackerint main (int argc, const char * argv[]){ NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; RetainTracker *tracker; tracker = [RetainTracker new]; // count: 1 [tracker retain]; // count: 2 [tracker autorelease]; // count: still 2 [tracker release]; // count: 1 NSLog (@"releasing pool"); [pool release]; // gets nuked, sends release to tracker @autoreleasepool { RetainTracker *tracker2; tracker2 = [RetainTracker new]; // count: 1 [tracker2 retain]; // count: 2 [tracker2 autorelease]; // count: still 2 [tracker2 release]; // count: 1 NSLog (@"auto releasing pool"); } return (0);}
第一个代码块是使用NSAutoreleasePool对象创建的自动释放池。和之前的语句相比,多了一个[tracker autorelease]语句,该语句做了啥?它并没有给引用计数器的值做操作,而是把该对象添加到自动释放池中,在自动释放池中也有一个引用指向了该对象。当自动释放池销毁时,会向改对象发送一条release消息。由于我们先向tracker对象发送了retain对象,计数器加1,然后发送release消息,计数器减1,但是此时tracker对象的dealloc方法并不会调用,因为new方法让计数器加1,所以pool对象的release方法没调用之前,tracker对象的计数器的值为1,当pool对象的调用release后,自动释放池的计数器为0,此时pool对象的dealloc方法会被调用,然后会想池中的对象发送release对象,那么此时tracker对象的计数器值会变为0,tracker对象的dealloc方法被调用,所以输出应该如下:
2015-02-01 00:12:02.426 09.02 RetainCount-2[860:58571] init: Retain count of 1.2015-02-01 00:12:02.428 09.02 RetainCount-2[860:58571] releasing pool2015-02-01 00:12:02.428 09.02 RetainCount-2[860:58571] dealloc called. Bye Bye.
另外一个@autoreleasepool关键字创建的自动释放池也是一样的过程。整个输出如下:
2015-02-01 00:18:23.932 09.02 RetainCount-2[876:61410] init: Retain count of 1.2015-02-01 00:18:23.933 09.02 RetainCount-2[876:61410] releasing pool2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] dealloc called. Bye Bye.2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] init: Retain count of 1.2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] auto releasing pool2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] dealloc called. Bye Bye.Program ended with exit code: 0
1 0
- Objective-c自学笔记(5)-自动释放池
- Objective c 自动释放池
- objective-C 自动释放池(autorelease pool)
- Objective-C Autorelease Pools(自动释放池)
- Objective-C自动释放池AutoreleasePool详解
- 【Objective-C基础】自动释放池
- Objective-C内存管理第五弹:自动释放池
- iOS学习(十一)Objective-C 自动释放池
- Objective-C: 继承与派生、MRC、自动释放池、
- 深入理解Objective-C: Autorelease Pool (自动释放池)
- objective-c 内存自动释放(1)
- Objective-c自学笔记(1)-类
- objective-C 的内存管理之-自动释放池(autorelease pool)
- [Objective-C] 自动释放池(Autoreleasepool)--拆迁队的外援
- objective-C 的内存管理之-自动释放池(autorelease pool)
- objective-C 的内存管理之-自动释放池(autorelease pool)
- Objective-C的自动释放池(autoreleasepool)、静态方法快速创建对象
- 【Objective-C】OC中自动释放池的基本概念和使用方法
- bzoj 1131: [POI2008]Sta
- HTTP报文
- 使用storyBoard的优缺点
- JQuery性能优化
- 机器学习十大算法的每个算法的核心思想、工作原理、适用情况及优缺点
- Objective-c自学笔记(5)-自动释放池
- GUI+定时器
- hd1997
- GRUB4DOS 直接引导XP.ISO安装
- Missing number
- intellij idea14修改代码自动补全快捷键
- 初识shellcode
- uva11636
- 多个线程之间共享数据的方式探讨(七)