今天我正在审查一些代码,我完全被愚弄了。我在代码中看到了类似的东西
...
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
对此你能说什么?你真的认为这是最好的行为(而且更符合逻辑)吗?感谢您分享您的知识!