【问题标题】:Comparing pointers of NSNumber objects instantiated with const integers比较用 const 整数实例化的 NSNumber 对象的指针
【发布时间】:2012-12-21 19:02:35
【问题描述】:

今天我正在审查一些代码,我完全被愚弄了。我在代码中看到了这样的东西

...
NSNumber *myNumber = [NSNumber numberWithInteger:4];
...
if (myNumber == [NSNumber numberWithInteger:4)
{
...
}
...

当我读到if 条件时,我的第一个想法是:哇,伙计!你怎么能那样做?您显然是在比较指针,所以当然if 中的代码将永远不会执行,因为您在正确的位置生成实例,所以对象永远不会相同!

我的(大)惊喜是if 实际上正在被执行!所以我生成了一些测试来加深对正在发生的事情的理解,我得到了这个:

NSInteger intValue = 5;
NSNumber *anIntNumber = [NSNumber numberWithInteger:intValue];
NSNumber *anotherIntNumber = [NSNumber numberWithInteger:intValue];
NSLog(@"%p vs %p -> %@", anIntNumber, anotherIntNumber, ((anIntNumber == anotherIntNumber) ? @"YES" : @"NO"));

这是结果:

0x7462560 vs 0x7462560 -> YES

然后我记得我在堆栈溢出中的某处读到,当程序开始时,常量 NSString 存储在内存堆栈中的某处。然后我运行这段代码来检查 NSString 实例是否发生了同样的事情:

NSString *aString = @"FOO";
NSString *anotherString = @"FOO";
NSLog(@"%p vs %p -> %@", aString, anotherString, ((aString == anotherString) ? @"YES" : @"NO"));

这是结果:

0x35cc vs 0x35cc -> YES

所以是的,虽然不是故意的,但实例是相同的。 我可以想象这些结果是,系统也在内存堆栈中的某处分配了所有用常量整数实例化的 NSNumber 对象。

但我现在的问题是:他们为什么要这样做?内存的浪费不是比生成实例的时间更重要吗?

然后我想:花车呢?由于二进制表示和所有这些东西,浮点数不能真正与等号运算符进行比较。这是最后的测试:

float floatValue = 5.41553f;
NSNumber *aFloatNumber = [NSNumber numberWithFloat:floatValue];
NSNumber *anotherFloatNumber = [NSNumber numberWithFloat:floatValue];
NSLog(@"%p vs %p -> %@", aFloatNumber, anotherFloatNumber, ((aFloatNumber == anotherFloatNumber) ? @"YES" : @"NO"));

这是唯一的预期结果!

0x712f180 vs 0x74299a0 -> NO

对此你有什么想说的吗?你真的认为这是最好的行为(而且更符合逻辑)吗? 感谢您分享您的知识!

【问题讨论】:

  • 这是编译器优化:因为它们都是不可变对象并且在同一范围内,所以它们可能被创建一次而不是两次,没有任何后果。
  • @RamyAlZuhouri 实际上这是一个类级别的优化。不是在编译时完成,而是在运行时完成。

标签: objective-c ios foundation


【解决方案1】:

== 运算符与 NSNumber 一起使用仅在某些情况下有效,因为 NSNumber 实现在内部使用了一些整数 0 到 X(12 或 15 或其他)的全局实例。

在内存中保存一打 NSNumber 对象的内存是微不足道的。

无论如何,永远不要使用== 运算符进行平等检查。始终使用isEqual:(或其变体)。永远不要依赖这样的实现细节或编译器优化。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
相关资源
最近更新 更多