2011-02-28 53 views
6

我发现一个Objective-C/cocoa框架的例子有以下代码。Objective-C/cocoa框架中NSAutoreleasePool的神奇之处是什么?

int main() 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    // Create an array 
    NSArray *month = [NSArray arrayWithObjects:@ ... nill]; 

    [pool drain]; 
} 
  • Q1:什么是这背后的魔力(为什么我需要有NSAutoreleasePool代码?)? NSAutoreleasePoolpool drain块之间发生了什么魔术?我看到我自己并不需要发布*month。这是因为它在NSAutoreleasePoolpool drain区块内吗? Q2:使用Xcode,我已经获得了main()函数。在这种情况下,我如何使用NSAutoreleasePoolpool drain

例如:

int main(int argc, char *argv[]) 
{ 
    //NSAutoreleasePool *pool = [[[NSAutoreleasePool] alloc] init]; 
    return NSApplicationMain(argc, (const char **) argv); 
} 

回答

4

Q1:神奇的是NSObject -autorelease实例方法调用NSAutoreleasePool + addObject:class方法。 NSObject实例汇集在当前的NSAutoreleasePool实例中。 NSAutoreleasePool -drain实例方法调用池实例的发布方法。

它与Apple和GNUstep的Cocoa实现不完全相同,但它是相似的。

我不知道为什么一个月不被释放,应当由排水释放。 Q2:你可以在任何你想使用的地方使用NSAutoreleasePool。实例化一个NSAutoreleasePool意味着当前池将被新实例改变。排水将回到当前池到先前的实例。

除了NSApplicationMain永远不会返回。它调用退出函数来退出应用程序并终止进程。

+0

我没有直接调用-autorelease。这是否被隐含地称为? – prosseek 2011-02-28 04:52:02

+0

是的@Prairiedogg说。 arrayWithObjects在内部调用autorelease。 – 2011-02-28 04:54:50

0

我是相当新的目标C,但让我这个给一条缝:

自动释放池是目标C来处理垃圾的方式采用比手动更简单的方式进行采集。

它通过计数引用来完成此操作,或者在这种情况下每次调用“保留”或“释放”。

所以,如果你有一个对象的实例中的“一”,你可以这样做:

这使得它变成了AutoreleasePool: [a autorelease];

这会告诉你想坚持的自动释放池给它一段时间: [a retain];

现在你调用[pool drain],它会注意到你有一个对a的引用,并且它不会释放内存。但是,如果您稍后调用[a release],则下一次调用[pool drain]时,它会看到没有其他引用,并取消分配内存。

我有一个鬼鬼祟祟的怀疑,我刚才谈到自己在圈而不做一大堆的道理,但这里是引用计数的维基百科文章:http://en.wikipedia.org/wiki/Reference_counting

+0

自动释放不同于垃圾收集; GC不需要额外的代码。 “保留”和“释放”与自动释放池无关; 'autorelease'将接收者添加到自动释放池堆栈中最顶层的自动释放池中,以便当该池被耗尽时,池将向其发送一个“释放”消息。 – 2011-02-28 04:55:00

+0

基本阅读:http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/ – 2011-02-28 04:55:37

+1

这很接近,但在一些重要细节上是错误的。例如,说“(autorelease池)对引用进行计数”或“[retain]”告诉autorelease池想要保留它“是不正确的。引用计数的基本操作是“保留”和“释放”;他们根本不涉及autorelease池。 'autorelease'只是延迟释放调用的一种方式,直到后来(特别是直到下一个'[pool drain]')。阅读Peter Hosey提供的参考,然后再读一遍:-) – 2011-02-28 06:39:25

3

Q1:

你不需要在您给出的示例中释放month实例,因为您调用的NSArray类方法(arrayWithObjects:)将返回一个自动释放的实例。按照Cocoa中的约定,以该类名称开头的类方法将返回该类的自动释放实例。这些示例:

[NSString stringWithFormat:@"Holla %@", @"back girl!", nil]; 
[NSArray arrayWithObjects:@"Holla", @"back", @"girl!", nil]; 

这两个都会返回它们各自的自动释放对象的实例。

+0

然后,我认为我不需要'NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];'code as'NSArray * month = [NSArray arrayWithObjects:@ ... nill];'无论如何都会自动释放。这是对的吗? – prosseek 2011-02-28 04:50:46

+0

@prosseek:不会。自动释放一个对象会把它放到最顶层的自动释放池中。在'main'中,不存在其他自动释放池,但是您创建的是其他自动释放池;因此,您需要创建一个池(隐式)将数组自动释放。否则,您会在控制台日志中看到一条日志消息,并且数组(无自动释放池释放它)将被泄漏。 – 2011-02-28 04:53:37

+0

如果在注释中没有自动释放对象的自动释放对象,例如变量“month”,则该对象从不释放,并导致内存泄漏。 – koo 2011-02-28 04:55:45