为什么有NSNumber这样奇怪的retainCounts?

NSNumber* n = [[NSNumber alloc] initWithInt:100]; NSNumber* n1 = n; 

在上面的代码中,为什么n的retainCount的值设置为2? 在代码的第二行中,我没有使用retain来增加retainCount的数量。


我发现了一个奇怪的情况。 其实retainCount取决于最初的数字:

 NSNumber *n = [[NSNumber alloc] initWithInt:100]; // n has a retainCount of 1 NSNumber *n2 = [[NSNumber alloc] initWithInt:11]; // n has a retainCount of 2 

根据这里的链接,可能会有一些优化在常见的NSNumbers(这可能不会发生在所有的实现中,因此@ dizy的retainCount为1的可能原因)下进行。

基本上,因为NSNumbers是不可变的,所以底层代码可以自由地给你一个相同数字的第二个副本,这可以解释为什么保留计数是两个。

n和n1的地址是什么? 我怀疑他们是一样的。

 NSNumber* n = [[NSNumber alloc] initWithInt:100]; NSLog(@"Count of n : %i",[n retainCount]); NSNumber* n1 = n; NSLog(@"Count of n : %i",[n retainCount]); NSLog(@"Count of n1: %i",[n1 retainCount]); NSLog(@"Address of n : %p", n); NSLog(@"Address of n1: %p", n1); 

根据你的更新,我给你的链接几乎肯定是问题。 有人进行了一个testing,发现从0到12的NSNumbers会给你重复的已经创build的(他们可能实际上是由框架创build,甚至在用户请求之前)。 其他12以上似乎给保留计数1。引用:

从我已经能够做的一点点检查,看起来好像你会得到“共享”版本的整数NSNumbers范围[0-12]的值。 即使值相等,任何大于12的值都会得到唯一的实例。 为什么十二? 没有线索。 我甚至不知道这是一个很难的数字或情况。

试用11,12和13 – 我想你会发现13是第一个给你一个非共享的NSNumber。

停止。 停下来。 永远不要看对象的retainCount 。 永远。 它不应该是API和可用。 你在痛苦

对于retainCount是有意义的。

保留计数是一个实现细节。 有时候,它们可能是有用的debugging工具,但是一般来说,你不应该关心它们。 你应该关心的是你遵循内存pipe理规则 。

举个例子,为什么看保留计数是不可靠的,这是一个完全合法的类,服从API合同,在任何情况下都会正确运行:

 @implementation CrazyClass - (id)retain { for(int i=0; i<100; i++) { [super retain]; } } - (void)release { for(int i=0; i<100; i++) { [super release]; } } @end 

…但是如果你检查了它的保留数量,你会认为你有一个“问题”。

这种精确的情况在实践中并不经常发生,但是它说明了为什么查看保留计数对于判断是否有错是毫无用处的。 对象通过您的控制之外的代码被保留在幕后。 例如,NSNumber有时候会caching实例。 对象获得autoreleased,这不反映在保留计数。 很多事情可能会发生,这将混淆保留计数。 有些class级可能甚至不能保留自己的留存点数。

如果你怀疑有泄漏,你应该检查真正的debugging工具,而不是通过保留计数。 而对于你正在编写的代码,你应该首先关注遵循上面链接的指导原则。

你不应该依赖对象的retainCount 。 您只能将其用作debugging帮助,而不能用于正常的控制stream程。

为什么? 因为它没有考虑到autorelease 。 如果一个对象被retain并且子节点autorelease d,它的retainCount将会增加,但就你而言,它的真正保留计数并没有被改变。 获得一个对象真正的保留计数的唯一方法是也计算它被添加到自动释放池链中的任何autorelease池的次数,试图这样做是在寻找麻烦。

在这种情况下, retainCount是2,因为在allocinitWithInt:某个地方,对象被retainautorelease d。 但是你不需要知道或关心这个,这是一个实现细节。

我想你还有别的事情…

  NSNumber* n = [[NSNumber alloc] initWithInt:100]; NSNumber* n1 = n; NSLog(@"n = %i",[n retainCount]); 

结果是1