[英]Autorelease Pool Blocks
当我偶然发现自动释放池块时,我最近阅读了高级内存管理文档。 文件说明:
您可以在循环内使用自动释放池块在下一次迭代之前处理这些对象。 在循环中使用自动释放池块有助于减少应用程序的最大内存占用量。[...]在块结束时释放在自动释放池块内发送自动释放消息的任何对象。
在块内创建的没有自动释放调用的对象怎么办? 我假设他们也将保留计数减少到0.然后,我的问题是,当在任何一种方式调用自动释放时,在块内创建的对象是否会在块结束时获得释放调用?
一个目的可以通过发送一个被释放-release
或-autorelease
消息。
使用-release
,引用计数立即递减,这可能导致释放。
使用-autorelease
延迟递减以使对象保持活动超出其创建范围。 例如,辅助方法-createFoo
可以返回一个自动释放的对象,以便调用者可以使用返回的对象,而不会在从方法返回时立即释放它,而不必担心谁负责释放它。
使用ARC,编译器会为您处理所有这些细节。 您需要知道的是,有时使用autorelease
对象会保持更长时间。
这种“保持活跃”行为会对以下循环产生影响:
- (void)foobar
{
for (/* a long time */) {
NSMutableString *s = [NSMutableString string];
// ...
}
}
NSMutableString
上的+string
方法将返回一个自动释放的对象。 这不会在循环迭代或方法结束时自动释放(好吧,ARC可以通过查看调用堆栈来做一些聪明的优化,但我们会忽略它)。 这意味着当你进入循环体内时,你将获得无限的内存增长。
请注意,如果我们使用了以下内容:
NSMutableString *s = [[NSMutableString alloc] init];
然后ARC会在循环体的末尾插入一个release
调用,字符串将立即释放。
要解决第一个示例的无限内存增长,您需要定义一个显式的自动释放池:
- (void)foobar
{
for (/* a long time */) {
@autoreleasepool {
NSMutableString *s = [NSMutableString string];
// ...
}
}
}
现在,在循环的每次迭代之后,自动释放池被销毁,并且在池内自动释放的任何对象(包括我们的字符串)将立即被释放。
所以这一切都取决于您调用的方法类型以及它们是否返回自动释放的对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.