通过“便利构造函数”初始化的返回对象

时间:2009-08-12 14:54:57

标签: objective-c memory-management initialization return-value autorelease

当一个实例方法返回一个用方便构造函数初始化的值时,我是否需要保留该对象然后在返回中自动释放,这样当方便构造函数的自动释放发生时,它不会删除该对象。

这个版本会在调用代码之前发布说明并使用retain或者其他东西获得所有权吗?

- (NSStringMutable *)test {
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"];
    return description;
}

或者它应该是这样吗?

- (NSStringMutable *)test {
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"];
    [description retain];                               
    return [description autorelease];
}

致电代码:

NSMutableString *testVar = [[NSMutableString alloc] initWithString:[object description]];

5 个答案:

答案 0 :(得分:9)

不,你应该没问题:

- (NSStringMutable *)test
{
    return [NSMutableString stringWithString:@"Test Value"];
}

这将使对象的保留计数为1,并且将在自动释放池中。

自动释放池在特定时间耗尽 - 它不像垃圾收集器。如果您正在实现一个事件处理程序(如按钮单击处理程序),那么当您从事件处理代码返回时,框架会自动释放自动释放池。

如果你使用过这个:

- (NSStringMutable *)test
{
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"];
    [description retain];                                                               
    return [description autorelease];
}

...然后该对象的保留计数为2,并且将在自动释放池中两次,并且实际上将以与上一代码示例相同的方式运行。

答案 1 :(得分:1)

你可以退货。这是自动释放的主要目的之一。除非您已经设置了自己的自动释放池,否则在下一次运行事件循环之前,池不会被耗尽。 memory management programming guide详细解释了所有这些 - 你应该阅读它,直到你对它感到满意为止。

旁注:如果这个不是安全且自动释放池会因某些奇怪的原因而提前耗尽,给它两个保留和两个自动释放不会有所作为。这些数字仍然是平衡的,所以它在某些时候仍然会被释放出来。

答案 2 :(得分:1)

我已经投了正确答案,我将其添加为样式注释:

您的通话代码不起作用,因为它在调用[object description]时正在调用[object test]

除非您真的希望能够更改字符串,否则不需要返回可变字符串。我个人试着尽量减少我编写的代码中的可变性,因为我觉得维护程序状态变化最小是更容易的。您只返回描述,所以我认为它不需要是可变的。 我知道这只是一些示例代码,所以也许我太挑剔了

您可以将其重写为:

-(NSString *)description {
    // Just return a static NSString. No need to worry about memory management.
    return @"Test Value";
}

如果您希望能够在调用代码中更改此返回字符串的值:

NSMutableString *testVar = [[NSMutableString alloc]initWithString:[object description]];

由于您已经对此字符串调用了alloc,因此您拥有它并负责在将来某个日期发布它。

或者,您可以使用我最喜欢的一些代码:

NSMutableString *testVar = [[object description] mutableCopy];

这将返回一个甚至是不可变对象的可变副本(当然,如果它符合NSMutableCopying协议)。您需要在某个阶段发送[testVar release]

并将此作为您问题的实际答案:如果您发送分配复制 mutableCopy 保留到对象,然后您拥有该对象并负责向其发送发布消息。您可以假设其他任何东西都返回一个自动释放的对象。

同样,我知道这只是你问过一个问题的示例代码的一小部分,但是如果按照上面的规则,你的大部分内存管理问题都会被排序。在您的第一个示例中,您没有发送任何消息,因此您不需要自己释放任何内存。但是,您的调用代码中有一个alloc,因此您拥有testVar,并且需要将其释放。

答案 3 :(得分:0)

不,您只需返回自动释放的值即可。原因是autorelease不是变量本身的函数,它是自动释放池的一个函数,除非你自己创建一个,否则它通常由运行循环管理。

答案 4 :(得分:0)

你接近第二个,但你不需要保留你在这里谈论的情况,事实上你不需要自己调用autorelease。

这是有效的,因为stringWithString将返回一个自动释放的对象:

 - (NSStringMutable *)test
 {
   return [NSMutableString stringWithString:@"Test Value"];        
 }

通常在使用Objective-C创建对象时,如果您正在调用便捷构造函数(不调用alloc和init),则返回值始终是自动释放的,因此stringWithString返回一个自动释放的对象,您可以返回。