保留/释放返回的对象

时间:2011-08-16 09:39:09

标签: objective-c memory-management retain

我是Objective-C的新手,所以这可能是一个愚蠢的问题。

我不禁看到ObjC与微软COM在内存管理方面的相似之处(AddRef / Release vs retain / release)。在COM环境中,在将对象返回给调用者之前,总是AddRefretain)对象或多或少地强加给你。从我到目前为止看到的(我是第三个到Cocoa® Programming for Mac® OS X (3rd Edition)),内存管理部分有些模糊。

假设没有GC,返回对象的惯用方法是什么?

5 个答案:

答案 0 :(得分:12)

阅读有关自动释放池的Memory Management Programming Guide

在Objective-C中,按照惯例,应该自动释放对象(除非返回对象的方法的名称以“alloc”,“new”,“copy”或“mutableCopy”开头)。自动释放的对象由池中的Objective-C跟踪并自动处理,这意味着您无需关心向它们发送最终版本。与COM相比,这大大简化了引用计数,这就是为什么在大多数情况下你没有看到对返回对象的任何release调用。相反,相同的约定指定由名称以alloc,new,copy或mutableCopy开头的方法返回的所有对象都是方法调用者的责任。您必须手动调用这些对象的释放,否则您的程序将有内存泄漏。

答案 1 :(得分:5)

Cocoa通过引入第三个兄弟来绕过COM中AddRef / Release的限制; autorelease

  • retain - 我需要这个,让它坚持下去。
  • release - 我不再需要它了,你可以立即删除它。
  • autorelease - 我不需要这个,但让它保持几秒钟以防其他人想先拿起它。

这个微小的添加允许大多数返回值为句柄 as-if 我们有垃圾收集。如果您对保持返回值不感兴趣,请不要做任何额外的事情。

为了实现这个目的,有一个约定(一个足够好的惯例,让编译器能够为即将到来的ARC自动为你做内存)

  • 开头的方法名称必须返回保留的实例:
    • alloc
    • copy
    • new
    • retain
  • 所有其他必须返回自动释放的实例。

在实践中如何应用它的三个示例实现:

-(NSString*)newHelloWorldString {
    NSString* s = [NSString stringWithString:@"Hello world"];
    // Apply retain because s in now autoreleased
    return [s retain];
}

-(NSString*)helloWorldString {
    NSString* s = [[NSString alloc] initWithString:@"Hello world"];
    // Apply autorelease because s is now retained.
    return [s autorelease];
}

-(NSString*)fullName {
    // No memory management needed, everything is autoreleased and good.
    NSString* fn = [self firstName];
    NSString* ln = [self lastName];
    NSString* s = [NSString stringWithFormat:@"%@ %@", fn, ln];
    return s;
}

答案 2 :(得分:1)

通常类似

return [object autorelease];

你可以留在另一端。

如果您计划在Lion / iOS5上部署或使用最新的SDK,那么请查看ARC。

答案 3 :(得分:-1)

基本上我会建议让接收它的类保留它。即stackoverflow类接收对象的答案。

-(void) setAnswer:(Answer*) _answer{
    self.answer = _answer; // If the answer is created from a returned message.
    [_answer release];
}

编辑:我想我可能已经把错误的东西放在那里,因为我正在第二次看它。意思是:

Answer *_answer = [stackoverflow createAnswer];
self.answer = _answer;
[_answer release];

答案 4 :(得分:-3)

如果你返回一个对象,由所有者来保留它,我会尽可能避免自动释放,因为一旦nspool启动,那些对象就会消失,如果它们仍然被使用,它将导致问题。

即答案*答案= [stackoverflow getAnswer],如果在getanswer方法中创建了答案,则任何人正在检索它,负责释放它。

有道理吗?