17.3 自动释放池示例
看一下本章最后一个执行例子,以保证真正地理解对象的引用计数、保持和释放/自动释放的工作方式。检查代码清单17-6,该程序定义了一个名为Foo的虚类,它有一个实例变量以及一个继承来的方法。
代码清单17-6
import<Foundation/NSObject.h>
import<Foundation/NSAutoreleasePool.h>
@interface Foo:NSObject
{
int x;
}
@end
@implementation Foo
@end
int main(int argc, char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
Foo*myFoo=[[Foo alloc]init];
NSLog(@“myFoo retain count=%x”,[myFoo retainCount]);
[pool drain];
NSLog(@“after pool drain=%x”,[myFoo retainCount]);
pool=[[NSAutoreleasePool alloc]init];
[myFoo autorelease];
NSLog(@“after autorelease=%x”,[myFoo retainCount]);
[myFoo retain];
NSLog(@“after retain=%x”,[myFoo retainCount]);
[pool drain];
NSLog(@“after second pool drain=%x”,[myFoo retainCount]);
[myFoo release];
return 0;
}
代码清单17-6输出
myFoo retain count=1
after pool drain=1
after autorelease=1
after retain=2
after second pool drain=1
该程序分配了一个新的Foo对象,并且将它赋值给变量myFoo。前面已经看到过,它的初始保持计数为1。然而,这个对象并不是自动释放池的一部分,因此,释放池时,这个对象并没有失效。随后,定义了一个新池,并且向myFoo发送一条autorelease消息将其添加到池中。请注意,它的引用计数并没有改变,这是因为将对象添加到自动释放池时,并不影响它的引用数,仅仅是为了以后释放而进行了标记。
然后,向myFoo发送retain消息。这使得它的引用数变为2。随后再次释放池时,myFoo的引用数减为1,这是因为在前面向它发送了autorelease消息,所以,当池被释放时,会向myFoo发送release消息。
因为myFoo在释放池之前是保持的,所以它的引用数在减1后仍大于0。因此,myFoo对象在池释放后仍然有效。当然,现在你必须亲自释放它,在代码清单17-6中,就是这样来释放对象并避免内存泄漏的。
如果对此仍有些疑惑,请重新阅读关于自动释放池的解释。理解代码清单17-6之后,就彻底理解了自动释放池及其工作机理。