8

给定以下代码:

int firstInt, secondInt;

firstInt = 5;
secondInt = 5;

NSNumber *firstNumber = [NSNumber numberWithInt:firstInt];
NSNumber *secondNumber = [NSNumber numberWithInt:secondInt];

为什么这两个 NSNumber 实例指向同一个地址?

这让我发疯!

当然,如果您将 secondInt 更改为“4”,则一切都按预期工作。

谢谢,杰里米

4

3 回答 3

12

这可能是编译器优化或实现细节:由于 NSNumber 是不可变的,因此不需要它们是单独的实例。

编辑:可能是考虑它的实现优化。可能 numberWithInt 在随后使用相同的整数调用时返回一个单例。

于 2010-11-24T18:16:17.717 回答
6

我的设计直觉告诉我,如果分数的身份与其单纯的价值不同,那么您应该对某种分数对象进行排序,而不是简单的 NSNumbers。

除此之外:在紧要关头,您可以像使用 NSNumber 一样使用普通的 NSValue。取出值需要做更多的工作,但是 NSValue 本身没有 NSNumber 对小值所做的实例合并行为。

一些练习所有三种行为的代码:

  // NSValues are always distinct:
  int foo = 5, bar = 5, outfoo, outbar;
  NSValue *one = [NSValue value:&foo withObjCType:@encode(int)];
  NSValue *two = [NSValue value:&bar withObjCType:@encode(int)];

  [one getValue:&outfoo];
  [two getValue:&outbar];
  NSLog(@"one: %@ %x = %d ; two: %@ %x = %d",
        [one class], one, outfoo,
        [two class], two, outbar);

  // by comparison with NSNumber behavior:
  NSNumber *three = [NSNumber numberWithInt:6];
  NSNumber *four = [NSNumber numberWithInt:6];

  NSLog(@"three: %@ %x = %d ; four: %@ %x = %d",
        [three class], three, [three intValue],
        [four class], four, [four intValue]);

  // except when the numbers are big:
  NSNumber *five = [NSNumber numberWithInt:8675309];
  NSNumber *six = [NSNumber numberWithInt:8675309];

  NSLog(@"five: %@ %x = %d ; six: %@ %x = %d",
        [five class], five, [five intValue],
        [six class], six, [six intValue]);

在我的 Mac 上,这会产生如下输出:

one: NSConcreteValue 42a8d0 = 5 ; two: NSConcreteValue 42a920 = 5
three: NSCFNumber 404380 = 6 ; four: NSCFNumber 404380 = 6
five: NSCFNumber 1324d0 = 8675309 ; six: NSCFNumber 106e00 = 8675309
于 2010-11-24T19:32:06.493 回答
3

因为它们具有相同的hash值,所以NSNumber从第一次分配中返回给您一个缓存的指针。

于 2010-11-24T18:17:03.457 回答