2009-03-18 4 views
1
NSNumber* n = [[NSNumber alloc] initWithInt:100]; 
NSNumber* n1 = n; 

В приведенном выше коде, почему значение n сохраняетCount установлено равным 2? Во второй строке кода я не использовал сохранение, чтобы увеличить количество saveCount.Почему NSNumber такие странные saveCounts?


Я нашел странную ситуацию. На самом деле retainCount зависит от исходного числа:

NSNumber *n = [[NSNumber alloc] initWithInt:100]; 
// n has a retainCount of 1 

NSNumber *n2 = [[NSNumber alloc] initWithInt:11]; 
// n has a retainCount of 2 

ответ

2

Я думаю, что у вас есть что-то еще ...

NSNumber* n = [[NSNumber alloc] initWithInt:100]; 
    NSNumber* n1 = n; 
    NSLog(@"n = %i",[n retainCount]); 

Результат 1

+0

Это очень странно, результат в моем xcode равен 2. следующий код скопирован из моего xcode: NSNumber * n = [[NSNumber alloc] initWithInt: 11]; \t NSNumber * n1 = n; \t NSLog (@ "% i", [n retainCount]); – Jiang

5

Стоп. Просто остановись. Никогда посмотреть на retainCount объекта. Когда-либо. Он никогда не должен был быть API и доступен. Вы просите боль.

Существует слишком много для retainCount, чтобы иметь смысл.

+0

Хотели бы вы уточнить, пожалуйста? – dizy

+0

Согласовано. Каждому 'alloc' нужен' release'. Это все, о чем вам следует беспокоиться. Что касается вас с помощью 'keepCount', значит, что вы можете делать с внутренними структурами Apple. Вы можете верить, что их код будет правильным (даже если это не так, это не ваша задача исправить). –

6

На основании этой ссылки here возможно, что под обложками для общих NSNumbers существует какая-то оптимизация (что может не произойти во всех реализациях, поэтому возможная причина, по которой @ dizy's keepCount равен 1).

В основном, поскольку NSNumbers не изменяются, базовый код может предоставить вам вторую копию того же номера, которая объясняет, почему счетчик удержания равен двум.

Каков адрес n и n1? Я подозреваю, что они такие же.

NSNumber* n = [[NSNumber alloc] initWithInt:100]; 

NSLog(@"Count of n : %i",[n retainCount]); 

NSNumber* n1 = n; 

NSLog(@"Count of n : %i",[n retainCount]); 
NSLog(@"Count of n1: %i",[n1 retainCount]); 
NSLog(@"Address of n : %p", n); 
NSLog(@"Address of n1: %p", n1); 

Основываясь на вашем обновлении, эта ссылка, которую я вам дал, почти наверняка является проблемой. Кто-то проверил тест и выяснил, что NSNumbers от 0 до 12 предоставят вам дубликаты уже созданных (они могут быть созданы платформой даже до того, как пользователь их запросит). Другие выше 12, казалось, дают сохранить кол 1. Цитирование:

С немного экзамена я был в состоянии сделать, это выглядит, как если бы вы получите «общие» версию целочисленных NSNumbers для значений в диапазоне [0-12]. Все, что больше 12, дает вам уникальный экземпляр, даже если значения равны. Почему двенадцать? Нет подсказки. Я даже не знаю, тяжело ли это или косвенное.

Попробуйте с помощью 11, 12 и 13 - Я думаю, вы обнаружите, что 13 - это первый, который предоставит вам неосновный NSNumber.

+0

Вы правы. я попробовал 13, saveCount стал 1. – Jiang

5

Retain counts - это деталь реализации. Иногда они могут быть полезны при отладке, но в целом вы не должны заботиться о них. Все, о чем вы должны заботиться, это то, что вы следите за memory management rules.

Для примера, почему, глядя на сохранение отсчеты ненадежно, это совершенно законно класс, который подчиняется контракта API и правильно вести себя в любых обстоятельствах:

@implementation CrazyClass 
    - (id)retain { 
     for(int i=0; i<100; i++) { 
      [super retain]; 
     } 
    } 

    - (void)release { 
     for(int i=0; i<100; i++) { 
      [super release]; 
     } 
    } 
@end 

... но если вы осмотрены сво сохранить счетчик , вы бы подумали, что у вас есть проблема.«

Этот точный случай не случается слишком часто на практике, но он иллюстрирует, почему поиск удерживаемых отсчетов бесполезен для того, чтобы сказать, что что-то не так. Объекты остаются за кулисами кодом вне вашего контроля NSNumber, например, иногда будут кэшировать экземпляры. Объекты получают автореализованный, что не отражается в счете удержания. Может произойти много вещей, которые будут путать счет сохранения. Некоторые классы могут даже не сохранять свои учетные записи, где вы можете их видеть.

Если вы подозреваете, что у вас есть утечка, вы должны проверить с помощью реальных средств отладки, предназначенных для этой цели, а не на том, чтобы выталкивать их за счет сохранения. И для кода, который вы пишете, вам следует в первую очередь заботиться о соответствии руководящим принципам, выше.

4

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

Почему? Потому что он не принимает во внимание autorelease s. Если объект равен retain ed и, соответственно, autorelease d, его retainCount будет увеличиваться, но, насколько вам известно, его значение real осталось недействительным. Единственный способ получить реальный счет за счет объекта - это также подсчитать, сколько раз он был добавлен в любой из пулов автозапуска в цепочке пулов авторезистов, и попытка сделать это требует неприятностей.

В этом случае retainCount 2, потому что где-то внутри alloc или initWithInt:, объект является retain ред и autorelease д. Но вам не нужно знать или заботиться об этом, это детализация реализации.

+1

Нет, вы не должны использовать его как вспомогательную помощь. Для этого это бесполезно. –