Почему NSNumber указывает на один и тот же адрес, когда значение равно? - PullRequest
7 голосов
/ 24 ноября 2010

С учетом следующего кода:

int firstInt, secondInt;

firstInt = 5;
secondInt = 5;

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

С какой стати эти два экземпляра NSNumber указывают на один и тот же адрес?

Это сводит меня с ума!

Конечно, если вы измените значение secondInt, скажем, «4», все будет работать как положено.

Спасибо, Жереми

Ответы [ 3 ]

12 голосов
/ 24 ноября 2010

Скорее всего, это либо оптимизация компилятора, либо детали реализации: поскольку NSNumber является неизменяемым, нет необходимости, чтобы они были отдельными экземплярами.

РЕДАКТИРОВАТЬ: возможно, оптимизация реализации задумывается об этом.Вероятно, numberWithInt возвращает одиночный код при последующем вызове с тем же целым числом.

6 голосов
/ 24 ноября 2010

Мой инстинкт проектирования говорит мне, что, если идентичность партитуры важна в отличие от ее простого значения, вы должны сортировать какой-либо объект партитуры вместо простых номеров NSN.

Но , что в стороне: в крайнем случае, вы можете использовать простое NSValue аналогично тому, как вы используете NSNumber. Это немного больше работы, чтобы получить значения, но само 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
3 голосов
/ 24 ноября 2010

Поскольку они имеют одинаковое значение hash, поэтому NSNumber возвращает вам кэшированный указатель из первого выделения.

...