自动释放池块

时间:2013-04-23 06:57:00

标签: ios memory-management autorelease

当我偶然发现自动释放池块时,我最近阅读了Advanced Memory Management文档。文档说明:

  

您可以在循环内使用自动释放池块在下一次迭代之前处理这些对象。在循环中使用自动释放池块有助于减少应用程序的最大内存占用量。[...]在自动释放池块内发送自动释放消息的任何对象都将在块结束时释放。

在块中创建的没有自动释放调用的对象怎么办?我假设他们也将他们的保留计数减少到0.然后,我的问题是,当在这个方法中,在块内创建的对象将在块的末尾获得释放调用时,调用自动释放是什么意思?

1 个答案:

答案 0 :(得分:2)

可以通过发送-release-autorelease消息来释放对象。

使用-release时,引用计数会立即减少,这可能会导致释放。

使用-autorelease递减递减以使对象保持活动超出其创建范围。例如,辅助方法-createFoo可以返回一个自动释放的对象,以便调用者可以使用返回的对象,而不会在从方法返回时立即释放它,而不必担心谁负责释放它。

使用ARC,编译器会为您处理所有这些细节。您需要知道的是,有时候使用autorelease对象会保持更长时间。

这种“保持活跃”行为会对以下循环产生影响:

- (void)foobar
{
    for (/* a long time */) {
        NSMutableString *s = [NSMutableString string];
        // ...
    }
}

+string上的NSMutableString方法将返回自动释放的对象。这是 not 在循环迭代或方法结束时自动解除分配(好吧,ARC可以通过查看调用堆栈来做一些聪明的优化,但我们会忽略它)。这意味着当你进入循环体内时,你将获得无限的内存增长。

请注意,如果我们使用了以下内容:

NSMutableString *s = [[NSMutableString alloc] init];

然后ARC会在循环体的末尾插入release调用,字符串会立即释放。

要解决第一个示例的无限内存增长,您需要定义一个显式的自动释放池:

- (void)foobar
{
    for (/* a long time */) {
        @autoreleasepool {
            NSMutableString *s = [NSMutableString string];
            // ...
        }
    }
}

现在,在循环的每次迭代之后,自动释放池被销毁,并且在池内自动释放的任何对象(包括我们的字符串)将立即释放。

所以这一切都取决于你调用的方法类型以及它们是否返回自动释放的对象。