iPhone Objective C内存分配

3
我知道使用Alloc、New或Copy时需要释放对象,如果我保留一个对象也需要释放它。但是如果在方法的结尾有以下语句:
return [[UIImage alloc] initWithContentsOfFile:path];

我拥有UIImage对象,因为我分配了内存空间,但我不再拥有对它的引用,因为它已经被返回给调用者。在我的dealloc()方法中,我无法释放它,因为我没有引用。

我的问题是,这样做是否正确:

return [[[UIImage alloc] initWithContentsOfFile:path] autorelease];

我认为在这种情况下,调用方可以保留返回的对象,如果他们想要拥有该对象并最终需要释放它,则必须自行释放。

谢谢您的帮助。

5个回答

5

1
谢谢,但是当使用 ARC 时,我想就不需要使用 autorelease 了,让编译器来处理所有的内存管理。 - NYTom
是的,ARC 会确保将释放发送给所有对象。 - Alexander

4
整个autorelease的目的都是围绕对象的返回而建立的。
- (id)bad {
    MyObj *obj = [[MyObj alloc] init];
    return obj;
}

这段代码可以正确返回所有内容,但是作为开发者,你必须确保稍后释放该对象。
- (id)moreBad {
    MyObj *obj = [[MyObj alloc] init];
    return [obj release];
}

这段代码在一个作用域内平衡使用了retain和release来使用内存,但返回的对象现在是垃圾值(预计会导致崩溃)。

- (id)good {
    MyObj *obj = [[MyObj alloc] init];
    return [obj autorelease];
}

这段代码是“延迟释放”的。也就是说,您可以在调用方保留对象,对象将是安全的。如果您没有NSAutoreleasePool,它肯定会被破坏,但这是非常罕见的情况,您很大程度上知道何时发生(最常见的情况是在没有“默认”自动释放池的新线程中开始)。
因此,常见做法是在一个作用域中平衡保留(和类似保留的)和释放方法。下一个建议是始终使用alloc-init-autoreleased对象,并在出现内存问题(例如在循环中自动释放许多对象)时切换到不同的释放方式。下一个建议是切换到ARC。

感谢详细的解释。 - Alexander

0
如果您使用 release,那么字符串将在返回之前被释放(方法将返回一个无效的对象)。使用 autorelease,表示您想要放弃所有权,但允许方法的调用者在字符串被释放之前使用它。这与 release 不同,后者会立即释放对象。

0
为什么要尝试分配它?直接说:
return [UIImage imageWithContentsOfFile:path];

没有需要分配的 - 也没有需要释放的。

同时,在使用ARC时,这是最佳选项,因为释放尝试会导致错误。


2
我同意,UIImage类有一个这样的方法,所以我不需要分配内存,因为UIImage类会拥有对象,因为它自己分配内存。我只是使用UIImage作为返回已分配类实例的示例。 - NYTom
该方法实际上返回一个自动释放的对象。 - Alexander
如果在当前方法中返回先前分配的对象(当然),说“return [object_bla_bla autorelease];”就足以避免内存泄漏。同样适用于“return [[[Bla_bla_Type alloc] initWith_bla_bla_or_whatever] autorelease];”。 - John Smith

0

两个答案都是正确的,但是你可能并不总是有一个方便的方法可用,所以我喜欢做的就是像你使用autorelease一样:

- (MySomethingClass*)giveMeAFancyObject{
    MySomethingClass *obj = [[[MySomethingClass alloc] init] autorelease];
    obj.name = @"Something";
    // do some setting up maybe
    return obj;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接