Почему количество сохранений @1 равно 7, 8 или 10?

Я создал пустое приложение для iOS на Xcode 4.4.1 и сделал следующее:

NSNumber *n1 = @1;
NSNumber *n2 = @2;
NSNumber *n3 = @3;
NSNumber *n100 = @100;

NSString *s = @"haha";
NSArray *a = @[n1, s];
NSDictionary *d = @{ @"ha" : @1, @3 : @"hello" };

NSLog(@"retain count of @1 is %i", [n1 retainCount]);
NSLog(@"retain count of @2 is %i", [n2 retainCount]);
NSLog(@"retain count of @3 is %i", [n3 retainCount]);
NSLog(@"retain count of @100 is %i", [n100 retainCount]);

NSLog(@"retain count of @\"haha\" is %i", [s retainCount]);

NSLog(@"retain count of array literal is %i", [a retainCount]);
NSLog(@"retain count of dictionary literal is %i", [d retainCount]);

и результат:

retain count of @1 is 10
retain count of @2 is 4
retain count of @3 is 5
retain count of @100 is 1
retain count of @"haha" is -1
retain count of array literal is 1
retain count of dictionary literal is 1

поэтому счетчик сохранения литерала массива и литерала словаря равен 1, а строковый литерал, как говорят, существует для всего запущенного приложения, поэтому он равен -1 (вероятно, это означает MAX unsigned int), но на самом деле выходит счетчик сохранения @1 как 7, 8 и 10 в разное время. Есть ли какое-то правило? Я обнаружил, что также могу выполнять [n1 retain] и [n1 release], и это будет соответственно увеличивать и уменьшать количество удержаний.


person Jeremy L    schedule 14.09.2012    source источник
comment
whentouseretaincount.com   -  person    schedule 14.09.2012
comment
Не используйте RetainCount. Посмотрите здесь, например, stackoverflow.com/questions/11507537/ или воспользуйтесь поиском!   -  person Mario    schedule 14.09.2012
comment
я не говорю, что использую continueCount для программирования. Я использую здесь для экспериментов и проверки числа должно быть то, что это   -  person Jeremy L    schedule 14.09.2012
comment
@Jeremy L Во-первых, это не причина отрицать правильный ответ, во-вторых, вы не можете использовать continueCount даже для этого.   -  person    schedule 14.09.2012
comment
@JeremyL просто для дополнительного акцента, то, что H2CO3 говорит о важности, вы не можете использовать continueCount, чтобы убедиться, что число является тем, чем оно должно быть. А причина очень проста: вы не знаете (и не можете) знать, каким оно должно быть.   -  person Analog File    schedule 14.09.2012
comment
Итак, вы говорите, вы не можете знать, каким оно должно быть, потому что вы не можете знать, каким оно должно быть. так какая польза от retainCount вообще? На самом деле, в большинстве случаев они действительно показывают значение, которое должно быть.   -  person Jeremy L    schedule 14.09.2012
comment
Точно, какая польза от retainCount вообще? Никто не знает.   -  person BoltClock    schedule 15.09.2012
comment
Честно говоря, мне это кажется небольшой ошибкой (в частности, пропущенной оптимизацией). Небольшие целочисленные NSNumbers обычно находятся в кэше чисел на iOS, поэтому им, вероятно, следует игнорировать сохранение и освобождение. Хотя, если iOS получит помеченные указатели, как OSX, это уже не будет иметь значения :)   -  person Catfish_Man    schedule 15.01.2013


Ответы (2)


Я не знаю.

Точно так же никто на StackOverflow.

Почему?

Потому что это знают только инженеры Apple. Foundation прост только в своем интерфейсе — базовая реализация представляет собой беспорядок. Он смешан со средой выполнения Objective-C, тщательно оптимизирован для множества возможных или вероятных обстоятельств, и если что-то упоминается в документах как вещь, на которую нельзя полагаться, к этому следует относиться серьезно.

- retainCount является одним из них. Это не для того, чтобы получить фактическое количество ссылок на конкретный экземпляр класса - его абсолютное значение бессмысленно. В случае этого метода имеют значение только относительные изменения. Использование пулов автоматического освобождения и автоматического подсчета ссылок (хотя здесь это и не применимо) добавляет еще один уровень двусмысленности.

Поэтому.

Да, и да, проверьте http://whentouseretaincount.com

person Community    schedule 14.09.2012
comment
+1, и не забывайте о бессмысленности нового уровня, привнесенной ARC - person Carl Veazey; 14.09.2012
comment
@Карл, спасибо! Да, это тоже веская причина, наряду с пулами автоматического выпуска - я обновил свой ответ. - person ; 14.09.2012
comment
+1 - никогда не следует читать и принимать решения на основе количества сохранений. Следуйте правилам памяти с сохранением и освобождением и полагайтесь на то, что он будет вести себя в соответствии с правилами. - person bryanmac; 14.09.2012
comment
так что ваш ответ заключается в том, что каждый пользователь Stackoverflow зашел и посмотрел, и вопрос, и никто не знает. - person Jeremy L; 14.09.2012
comment
@Jeremy L нет, я не говорил, что они пришли, посмотрели и не знали этого. Я сказал, что никто, кроме Apple, не может этого знать. - person ; 14.09.2012

Я думаю, это указывает на причину: каждый раз, когда встречается @1, это что-то вроде [[[NSNumber alloc] initWithInt:1] autorelease], и кажется, что он возвращает один и тот же объект. Итак, когда сделано следующее:

NSMutableArray *arr = [[NSMutableArray alloc] init];
for (int i = 0; i < 300; i++) {
    [arr addObject:@1];
}

количество сохранений фактически становится 610. И это то же самое, если сделать следующее:

NSMutableArray *arr = [[NSMutableArray alloc] init];
for (int i = 0; i < 300; i++) {
    [arr addObject:[[[NSNumber alloc] initWithInt:1] autorelease]];
} 

(Обновление: это 610, потому что количество сохранений увеличивается на 1 при использовании @1, а в другой раз, когда оно сохраняется массивом, так что общее количество составляет 600 раз). Это предполагает, что любое использование @1 в любом месте увеличит количество сохранений, и этот объект NSNumber, вероятно, помещается в пул автовыпуска одинаковое количество раз.

person Jeremy L    schedule 14.09.2012
comment
Это даже не просто @1, а [NSNumber numberWithInt:1] и так далее. Это более интересный результат; значения счетчика сохранения являются лишь очень неточным индикатором (и, возможно, в других ситуациях совершенно вводящим в заблуждение) оптимизации, происходящей внизу. Чтобы удовлетворить свое любопытство, используйте отладчик и профилировщики, чтобы понять, что происходит, потому что использование retainCount — это не только плохая инженерия, но и плохая наука. - person Carl Veazey; 14.09.2012
comment
по крайней мере, это дает вам представление о том, что может происходить, поэтому я не знаю, как можно прийти к выводу, даже экспериментируя и проверяя это, что это плохо. Это интересный случай, когда alloc предположительно каждый раз возвращает другой объект, но в приведенной выше строке alloc и init на самом деле каждый раз возвращают один и тот же объект. - person Jeremy L; 14.09.2012
comment
Это дало мне догадку, поэтому я не говорю, что это не совсем бесполезно, и я бы никогда не сказал, что использование чего-либо для создания вдохновения — это плохо. Но его нельзя надежно использовать для рассуждений или моделирования вашей программы, потому что это, по сути, причуда реализации. - person Carl Veazey; 14.09.2012
comment
как я уже говорил много раз, я никогда не собирался использовать его для обычного программирования. Я не знаю, почему люди видят retainCount и автоматически сходят с ума. - person Jeremy L; 14.09.2012
comment
Ужас в том, что, в конечном счете, это пустая трата времени; какие бы подсказки ни обнаружил retainCount, всегда есть альтернативная подсказка, которую, как правило, так же легко получить, и она гораздо лучше указывает на то, что на самом деле происходит. В этом случае, если бы вы распечатали указатели объектов из NSLog(@"%p", obj);, вы бы увидели, что объекты являются одиночками, и, таким образом, поведение сохранения/освобождения будет неопределенным. - person bbum; 14.09.2012
comment
это заставляет вас смотреть глубже, не так ли. Конечно, некоторые люди могут счесть более глубокие исследования пустой тратой времени. - person Jeremy L; 14.09.2012
comment
Да, то, что это послужило катализатором ваших исследований, безусловно, означает, что оно имеет некоторую ценность! Не хотел подразумевать иное. Дело, однако, в том, что если вы хотите исследовать goop сохранения/освобождения/распределения, есть гораздо лучшие инструменты, такие как печать адреса объекта для обнаружения синглетонов и использование инструмента Allocations с включенным счетчиком ссылок отслеживания, чтобы увидеть как счетчик сохранения история объекта и трассировка всех вызовов удержания/освобождения. - person bbum; 14.09.2012