0

我最近在阅读Advanced Memory Management文档时偶然发现了 Autorelease Pool Blocks。该文档指出:

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

在块内创建的没有自动释放调用的对象怎么办?我假设他们的保留计数也减少到 0。然后,我的问题是,无论哪种方式,在块内创建的对象将在块结束时获得释放调用时调用 autorelease 有什么意义?

4

1 回答 1

2

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

随着-release引用计数立即递减,这可能导致释放。

随着-autorelease递减的延迟,以使对象在其创建范围之外保持活动状态。例如,辅助方法-createFoo可以返回一个自动释放的对象,以便调用者可以使用返回的对象,而无需在从方法返回时立即释放它,也不必担心谁负责释放它。

使用 ARC,编译器会为您处理所有这些细节。您需要知道的是,有时使用autorelease.

这种“保持活动”行为对以下循环有影响:

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

+stringon 方法将NSMutableString返回一个自动释放的对象。这不会在循环迭代或方法结束时自动释放(嗯,ARC 可以通过查看调用堆栈进行一些巧妙的优化,但我们将忽略这一点)。这意味着当您在循环体内时,您将获得无限的内存增长。

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

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

然后 ARC 将release在循环体的末尾插入一个调用,并且该字符串将立即被释放。

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

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

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

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

于 2013-04-23T07:32:37.977 回答