Objective-C在函数中返回alloc'd内存==坏?

时间:2009-11-06 00:09:50

标签: iphone objective-c memory-management

这是在iPhone上。

那么如果我有像

这样的功能呢?
- (SomeObject*)buildObject;

我是否需要传入一个我已经在外部分配的变量,如

- (void)assignObject(SomeObject** out);

或者我可以吗

- (SomeObject*)buildObject
{
   return [[[SomeObject alloc] init] autorelease];
}

并像

一样使用它
SomeObject* obj = [[otherObject buildObject] retain];

我想做最后一个,但据我所知,这是未定义的,因为autorelease只保证对象直到函数结束?

5 个答案:

答案 0 :(得分:6)

在Objective-C中,内存管理合同如下:调用alloc的人负责调用release。如果构造函数调用[[[class alloc] init] release],则会快速创建并销毁该对象。

要解决这个问题,构建函数需要使用自动释放,如下所示:

return [[[Class alloc] init] autorelease];

注册要在当前运行循环结束时释放的对象,除非保留它,例如构造函数的调用者。在您的情况下,第二个示例正是您想要做的。

所以:

- (SomeClass*) buildObject {
   return [[[SomeClass alloc] init] autorelease];
}

- (void) doSomething {
   c = [self buildObject];
   // Call [c retain] if you want c to stay around after the current run
   // loop is finished and clean it up later, e.g. in your delloc method.
}

答案 1 :(得分:4)

如何在Cocoa中解决这个问题;阅读文档了解详情。

基本上,如果您的方法以 init 复制开头,则会返回一个保留的对象,您必须释放它。
如果您提供便利方法,则返回自动释放的对象。

这意味着:

- (id) initMyObject
{
    self = [super init];
    if (self) {
        // do something
    }
    return self
}

➔您必须释放使用此方法获得的对象

- (MyObject *) myObject
{
    return [[[MyObject alloc] initMyObject] autorelease];
}

➔这是一种方便的方法 - 该对象是由该方法自动释放的,你必须保留它如果你要保持它的时间长于自动释放池清空(你应该假设在当前方法结束)。

答案 2 :(得分:1)

Autorelease保证对象直到当前NSAutoreleasePool的释放/排出。

从方法中返回自动释放的对象是完全可以接受的(和标准做法)。

答案 3 :(得分:1)

你可以做你想做的事。在释放当前自动释放池之前,Autorelease不会向对象发出释放消息。发生这种情况要么是因为你明确地要求它(通过分配+启动NSAutoreleasePool然后将其耗尽),要么是因为系统这样做了。系统自动释放池的创建和排放发生在事件周期的开始和结束时;来自内存管理编程指南:

  

自动应用套件   在一个开头创建一个池   事件循环(或事件循环迭代),   例如鼠标按下事件,和   最后发布它,所以你的代码   通常不必担心   它们。

在实践中,这意味着您想要做的事情是安全的,因为您编写的所有代码将在一个事件周期内一起执行。

答案 4 :(得分:0)

使用最后一个是安全的。我在每个应用程序中都使用这种风格,从未遇到过问题。自动释放将持续许多很多很多执行周期,比函数结束时间长得多。