为什么 NSNumber 值相等时指向同一个地址?

发布于 2024-10-04 10:04:01 字数 332 浏览 8 评论 0原文

给出以下代码:

int firstInt, secondInt;

firstInt = 5;
secondInt = 5;

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

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

这让我发疯!

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

谢谢, 杰里米

Given the following code:

int firstInt, secondInt;

firstInt = 5;
secondInt = 5;

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

Why on Earth do those two NSNumber instances are pointing to the same address?

This drives me crazy!

Of course, if you change secondInt to, say '4', all works as expected.

Thanks,
Jérémy

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时间海 2024-10-11 10:04:01

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

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

This is likely either a compiler optimisation or an implementation detail: as NSNumber is immutable there's no need for them be separate instances.

EDIT: probably an implementation optimisation thinking about it. Likely numberWithInt returns a singleton when called subsequently with the same integer.

风轻花落早 2024-10-11 10:04:01

我的设计直觉告诉我,如果分数的身份与它的单纯值不同很重要,那么您应该对某种分数对象而不是普通的 NSNumber 进行排序。

但是除此之外:在紧要关头,您可以像使用 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

My design instinct tells me that, if the score's identity is important as distinct from its mere value, you should be sorting some kind of score object instead of plain NSNumbers.

But that aside: In a pinch, you can use plain NSValue similarly to how you're using NSNumber. It's a little more work to get values out, but NSValue itself doesn't have the instance coalescing behavior NSNumber does for small values.

Some code that exercises all three behaviors:

  // 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]);

On my mac this yields output like:

one: NSConcreteValue 42a8d0 = 5 ; two: NSConcreteValue 42a920 = 5
three: NSCFNumber 404380 = 6 ; four: NSCFNumber 404380 = 6
five: NSCFNumber 1324d0 = 8675309 ; six: NSCFNumber 106e00 = 8675309
始终不够 2024-10-11 10:04:01

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

Because they have the same hash value, so NSNumber gives back to you a cached pointer from the first allocation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文