1

我有一个问题现在可能没有任何实际用途,因为 ARC 受到高度鼓励,但我正在研究内存管理,有些东西我不太明白。

我有这个方法

+(NSNumber *)releaseTooEarly
{
    NSNumber *createdNumber = [[NSNumber alloc] initWithInteger:5];

    NSLog(@"retain count before release: %d", createdNumber.retainCount); //Prints 2

    [createdNumber release];

    NSLog(@"%@", createdNumber); //Prints 5

    return createdNumber;
}
  1. 如果对象刚刚创建,保留计数应该是 1 而不是 2?
  2. 我知道在这种情况下我应该使用 autorelease 以便我可以返回该值,并且调用者可以在它被释放之前使用它。我虽然如果我使用保留它会立即释放对象,但下一个 NSLog 显示它仍然存在,并且值成功返回。

我想知道我是否在一个不允许我在函数中释放对象的自动释放池中。

我知道我应该使用 ARC,但我只想了解这个结果的原因。

4

1 回答 1

2

您永远不应依赖保留计数的特定值(请参阅http://whentouseretaincount.com)。

在这种特殊情况下(可以在http://www.opensource.apple.com/source/CF/CF-476.19/CFNumber.c中看到),为 (-1) 和 12 之间的整数值NSNumber 缓存创建的对象,所以打电话

[[NSNumber alloc] initWithInteger:5];

重复将始终返回相同的实例。缓存包含一个对对象的附加引用,这是 的原因retainCount == 2,并且还解释了为什么释放对象时对象实际上并未被销毁。

但这只是实现细节!!. 如上所述,您不应该使用保留计数。即使一个对象被释放,也不一定意味着该对象的内存无效,因此访问该对象可能会显示结果。

规则见《高级内存管理编程指南》中的“基本内存管理规则” :

  • 你必须最终release还是你拥有的autorelease对象。
  • 您拥有使用名称以“alloc”、“new”、“copy”或“mutableCopy”开头的方法创建的对象</li>
  • 如果您使用 获得所有权,则您拥有一个对象retain

您的方法的正确版本是

+ (NSNumber *)releaseCorrectly
{
    NSNumber *createdNumber = [[[NSNumber alloc] initWithInteger:5] autorelease];
    return createdNumber;
}

autorelease平衡,alloc但确保对象在返回调用方法时仍然有效。它将在当前自动释放池被销毁时释放,例如当程序控制返回到主事件循环时。

于 2013-06-19T11:45:07.737 回答