it-swarm.cn

NSAutoreleasePool自动释放池如何工作?

据我了解,使用 alloc new copy 创建的任何内容都需要手动释放。例如:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

不过,我的问题是,这不是有效吗?:

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}
94
James Sumners

是的,你的第二个代码snippit是完全有效的。

每次--autorelease被发送到一个对象,它被添加到最里面的自动释放池。当池耗尽时,它只是向池中的所有对象发送-release。

自动释放池只是一种便利,允许您推迟发送 - 直到“以后”。 “稍后”可能会在几个地方发生,但Cocoa GUI应用程序中最常见的是在当前运行循环周期结束时。

65
kperryua

NSAutoreleasePool:排水与释放

由于drainrelease的功能似乎引起了混淆,因此在这里可能值得澄清(虽然这在 文档 ...中有所涉及)。

严格地说,从全局角度来看drain not 等同于release

在引用计数环境中,drain执行与release相同的操作,因此这两者在该意义上是等效的。要强调,这意味着如果使用drain而不是release,则执行 not 泄漏池。

在垃圾收集环境中,release是无操作。因此它没有效果。另一方面,drain包含一个收集器的提示,它应该“在需要时收集”。因此,在垃圾收集环境中,使用drain有助于系统平衡收集扫描。

37
mmalc

正如已经指出的那样,您的第二个代码段是正确的。

我想建议一种更简洁的方法来使用适用于所有环境的自动释放池(引用计数,GC,ARC),并避免排放/释放混淆:

int main(void) {
  @autoreleasepool {
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
  }
}

在上面的例子中,请注意 @autoreleasepool block。这是记录 这里

17
Neovibrant

不你错了。文档清楚地表明,在非GC下,-drain相当于-release,这意味着NSAutoreleasePool将泄露。

7
kperryua

我发现这个链接给出了关于何时以及如何使用NSAutoReleasePool的最佳解释: AutoReleasePool

1
Wayne Lo

发送自动释放而不是释放到对象会延长该对象的生命周期,至少直到池本身耗尽(如果随后保留该对象,则可能会更长)。对象可以多次放入同一个池中,在这种情况下,每次将对象放入池中时都会收到一条释放消息。

0
Hardik Mamtora

是的,你的代码是完美的,如果你正在使用垃圾收集,只要你完成它就可以将字符串设置为nil。垃圾收集不利于您的应用程序的性能,所以我不建议使用它:P

0
Antwan van Houdt

我从Apple读到的内容:“在自动释放池块的末尾,在块中接收到自动释放消息的对象被发送一个释放消息 - 一个对象在每次在块中发送自动释放消息时都会收到释放消息。 “

https://developer.Apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

0
Gagan_iOS