在实例方法中分配对象的推荐方法是什么,稍后将返回?

时间:2011-02-02 23:19:29

标签: iphone objective-c memory-management

例如,请查看以下示例:

代码1

-(NSString*)getString{
    return [[[NSString alloc] initWithFormat:@"test"] autorelease];
}

-(void)printTestString{
    NSString *testStr = self.getString;
    [testStr retain]
    NSLog(@"%@",testStr);
    [testStr release]
}

代码2

-(NSString*)getString{
    return [[NSString alloc] initWithFormat:@"test"];
}

-(void)printTestString{
    NSString *testStr = self.getString;
    NSLog(@"%@",testStr);
[testStr release];
}

代码1和代码2应该是有效的代码片段,不应出现泄漏。

代码1使用autorelease,因此返回变量必须保留在printTestString中并在使用后释放。因此,由于自动释放,这里有一个小的开销。

代码2不会在getString中释放NSString,因此您必须在使用它之后才释放它。似乎你必须少写,你没有开销,因为没有使用自动释放。

哪一种是事实上的“标准”方法?

我问自己的另一件事。可以在getString中自动释放并使用

保留
[testStr retain]

是一个问题,当autorelease池在

之后立即释放变量时
NSString *testStr = self.getString;

然后字符串就会消失。这是可能的还是编译器会阻止那种事情?

由于

-Sebo

2 个答案:

答案 0 :(得分:2)

这样做:

-(NSString*)getString{
    return [[[NSString alloc] initWithFormat:@"test"] autorelease];
}

-(void)printTestString{
    NSString *testStr = self.getString;
    NSLog(@"%@",testStr);
}

您的getString方法自动释放NSString,这意味着printTestString不需要保留或释放它。 getString中的自动释放是有意义的,因为它分配了对象,因此是对象的“所有者”。我建议在继续之前研究Objective-C的内存管理规则,因为它们非常重要。

http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH

答案 1 :(得分:2)

Jake的答案对于从方法返回对象所需的几乎所有情况都是正确的,但在某些情况下,您可能希望返回未自动释放的内容。从Memory Management Programming Guide(Mac版本,但它们是相同的规则):

  

如果您拥有对象的所有权   使用名称为的方法创建它   以“alloc”或“new”开头   包含“复制”(例如,alloc,   newObject,或mutableCopy),或者如果你   发送保留信息。

另外,来自Coding Guidelines for Cocoa

  

在你的方法和功能中   返回对象值,确保   你自动释放这些值   除非他们是对象创造或   对象复制方法(new,alloc,copy   和他们的变种)。 “自动释放”   这种背景并不一定意味着   对象必须是明确的   自动释放 - 即发送   以前自动释放到对象   归还它。从一般意义上说,它   只是意味着返回值不是   被来电者释放。

     

出于性能原因,它是   建议避免自动释放   方法实现中的对象   你可以,特别是代码   可能经常执行   在短期内;一个例子   这样的代码将是一个未知的循环   并且可能有很高的循环次数。

因此,包含前缀allocnew的方法,或按惯例包含单词copy的方法将让您返回未自动释放的对象。事实上,Clang Static Analyzer了解这个约定,并假设从遵循这些命名规则的方法返回非自动释放的对象。

在我不希望返回自动释放的对象(我不想管理自动释放池的紧密循环等)的情况下,我使用了new前缀。同样,几乎在所有情况下都会推荐返回自动释放的对象,但有时您可能希望避免这种情况。