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

问题描述:

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

这个版本会在调用代码之前描述并取得保留或所有权吗?

- (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]]; 

不,你应该是罚款:

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

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

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

如果您用过这样的:

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

...那么对象将有一个保留的2计数和将在自动释放池两次,实际上会以同样的方式表现为在前面的代码示例。

+0

+1这回答了问题 – Abizern 2009-08-12 15:11:08

+2

你是对的,但尽量避免谈论保留计数,他们是一个红鲱鱼 - 没有保证NSMutableString会返回一个自动释放对象,只是它返回一个可变字符串,你目前不拥有。您可以将结果安全返回到您的调用仅仅是因为内存managemnt规则明确地说:“这方法也可以安全地将对象返回到它的调用”。 2009-08-13 03:14:37

+2

这是一个很好的观点。我发现从保留数量的角度来思考解释事物是很方便的。你是对的 - 你知道的只是stringWithString返回一个其他人拥有的对象。在这种情况下,由于NSMutableString实际上分配了该对象,因此NSMutableString负责释放它。 虽然我觉得这些便利构造函数(非init构造函数)通常会返回自动释放对象。如果我遇到不以这种方式行事的人,我会感到惊讶。 – 2009-08-14 19:44:32

不,你可以简单地返回自动释放的价值。原因是autorelease不是变量本身的函数,它是autorelease池的一个函数,除非你自己创建一个函数,它通常由运行循环管理。

您已经接近第二个,但您并不需要保留您在此处讨论的案例,实际上不需要自己调用autorelease。

这是有效的,因为stringWithString就已经返回自动释放的对象:创建使用Objective-C,如果你在呼唤一个便捷构造对象时

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

一般(没有要求alloc和INIT)的返回值总是自动释放,所以stringWithString返回一个自动释放的对象,你可以返回。

您可以返回它。这是autorelease的主要目的之一。除非你已经建立了自己的自动释放池,否则在下一次运行事件循环之前,池不会被排空。 memory management programming guide详细解释了所有这些 - 你应该阅读,直到你感觉舒服。

注意:如果这个不是安全,autorelease池会因为一些离奇的原因而提早耗尽,给它两个保留和两个autoreleases没有什么区别。这些数字仍然是平衡的,所以它仍然会在某个时候被释放。

我已经投票了正确的答案,我加入这个作为一种风格注:

调用代码是行不通的,因为它是调用[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]]; 

既然你已经呼吁该字符串页头,你拥有它,并负责在将来的某一天释放它。

或者,你可以用我最喜欢的码位的一个:

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

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

而且,以配合这作为一个实际的回答你的问题:如果你发送ALLOC复制mutableCopy,或保留到一个对象,那么你就拥有该对象,并负责发送它是一个版本消息。你可以假设其他东西都返回一个自动释放对象。

同样,我知道这只是示例代码的快速位,你问一个问题,但如果你坚持,你已经得到了大部分的排序内存管理问题,上述规则。在你的第一个例子中,你没有发送这些消息,所以你不需要自己释放任何内存。但是,您的呼叫代码中有一个alloc,因此您拥有testVar,您需要将其释放。

+0

感谢您的意见。我不知道mutableCopy。你是对的,这只是我的问题的一个例子。感谢您的阐述。我对目标c相当陌生,我甚至没有返回一个可以传递给NSMutableString的initWithString的NSString。谢谢(你的)信息。 – Brian 2009-08-12 17:09:56