Вопрос

Насколько я понимаю, оба из них создают NSMutableString, только первый принадлежит системе, а второй принадлежит мне (т.Мне нужно его выпустить).Есть ли какая-то конкретная причина, по которой мне следует использовать тот или иной вариант, на первый взгляд кажется, что проще использовать первый?И является ли первое лучше, поскольку оно дает компилятору ощущение размера?

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

ИЛИ

NSMutableString *newPath = [[NSMutableString alloc] init];

РЕДАКТИРОВАТЬ ...ТАКЖЕ

Я вижу много объявлений, написанных в две строки (т.е.)

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];

Лично я предпочитаю остроту, это просто еще один пример личного стиля?

Это было полезно?

Решение

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

ИЛИ

NSMutableString *newPath = [[NSMutableString alloc] init];

Есть ли какая-то конкретная причина, по которой мне следует использовать тот или иной вариант, на первый взгляд кажется, что проще использовать первый?

Да.Всегда производите автоматическое освобождение немедленно, если у вас нет особых причин не делать этого.

Первая причина в том, что очень легко забыть написать release сообщение.Если вы автоматически освобождаете объект в том же операторе, где вы его создали (как в [[[… alloc] init] autorelease]), забыть это гораздо труднее и гораздо очевиднее, когда вы это сделаете.Удобные фабричные методы (такие как stringWithCapacity:) автоматически освободить объект за вас, так что, как и при автоматическом освобождении его самостоятельно, вам не придется беспокоиться об его освобождении позже.

Во-вторых, даже если вы не забудете написать отдельный release сообщение, его легко не заметить.Два способа раннего возврата:

NSString *str = [[NSString alloc] initWithString:@"foo"];

BOOL success = [str writeToFile:path atomically:NO];
if (!success)
    return;

[str release];

и выбрасываемые или распространяемые исключения:

NSString *str = [[NSString alloc] initWithString:@"foo"];

//Throws NSRangeException if str is not in the array or is only in the array as the last object
NSString *otherStr = [myArray objectAtIndex:[myArray indexOfObject:str] + 1];

[str release];

«Конкретная причина не делать этого», как правило, заключается в том, что у вас есть узкий цикл, который создает множество объектов, и в этом случае вы можете захотеть вручную управлять как можно большим количеством объектов в цикле, чтобы сохранить количество объектов. вниз.Однако, делайте это только в том случае, если у вас есть доказательства того, что это ваша проблема (будь то точные числа из Shark, точные числа из Instruments или ваша система попадает в пейджинговый ад всякий раз, когда этот цикл выполняется достаточно долго).

Другие, возможно, лучшие решения включают разделение цикла на два вложенных цикла (внешний для создания и очистки пула автоматического выпуска для внутреннего цикла) и переключение на NSOperation.(Однако убедитесь, что вы установили ограничение на количество операций, выполняемых очередью одновременно, иначе возможно, вам будет еще проще попасть в пейджинговый ад.)

И является ли первое лучше, поскольку оно дает компилятору ощущение размера?

Это лучше, но не по этой причине.

Для компилятора это просто еще одно сообщение класса.Компилятор не знает и не заботится о том, что он делает;для всего, что он знает и заботится, stringWithCapacity: — это сообщение пользователю о воспроизведении песни.

Это дает Нсмутаблестринг подсказка о размере — класс будет знать, сколько места для хранения символов он может захотеть первоначально выделить.Какую бы выгоду вы от этого ни получили, она, вероятно, невелика (по крайней мере, на Mac), но если у вас есть под рукой информация, почему бы не использовать ее?И наоборот, я бы не стал изо всех сил пытаться вычислить это.

Я вижу много объявлений, написанных в две строки (т.е.)

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];

Лично я предпочитаю остроту, это просто еще один пример личного стиля?

Да.Однако существует определенный риск, если оставить переменную неинициализированной.Обязательно включите настройку сборки «Запустить статический анализатор», если решите сделать это привычкой.

Другие советы

Первое не обязательно предназначено для компилятора, а скорее представляет собой предложение для строки относительно того, как она может оптимизировать хранение своих данных.Это наиболее полезно для NSDictionary/NSArray/NSSet, который иметь возможность внутренне изменять свои реализации в зависимости от размера их набора данных.

В остальном вы правы:единственная разница - это вопрос собственности.Я почти никогда не использую WithCapacity методы, а лучше просто использовать [NSMutableString string] или [NSMutableArray array], но, по моему мнению, это всего лишь вопрос стиля, и вы ничего не выиграете и не потеряете, используя одно вместо другого.

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

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

Я считаю, что инициализация в две строки — это просто стиль, но я бы не стал использовать вариант из двух строк, поскольку вы определяете переменную, не присваивая ей значения, даже если вы находитесь на следующей строке.Я предполагаю, что этот вид зеркального объявления/инициализации переменных-членов, но лично мне это не очень нравится.

Вы поднимаете правильные вопросы.Это действительно зависит от того, что вы делаете, но для общих приложений для iPhone я бы посоветовал просто использовать первое.Это будет автоматически очищено, когда счетчик ссылок достигнет 0, и вам не придется об этом беспокоиться.

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

Я бы посоветовал, как правило, использовать второй вариант, когда у вас есть для этого веская причина.

Вы правы по всем пунктам!

Я не уверен, насколько велика разница в подсказке о размере/емкости, но дополнительная информация, безусловно, должна позволить среде выполнения принимать более правильные решения.

Зачем использовать один стиль вместо другого?А когда же выпускаются автовыпускаемые объекты?Есть две неочевидные причины, почему это может иметь значение.Во-первых, когда метод использует много памяти, которую можно немедленно освободить.(Думаю, вы также можете использовать локальный пул автоматического выпуска.) Во-вторых, я считаю, что использование автоматического выпуска может скрыть утечки памяти и затруднить отладку некоторого кода.Ваш опыт может варьироваться в зависимости от возраста и качества кода.

Когда я впервые начал разрабатывать приложения для iPhone, я постоянно использовал автоматически выпускаемые объекты.Это было удобно, потому что я не до конца понимал, как все это работает и обычно все срабатывало правильно.В наши дни я склонен ошибаться в сторону освобождения памяти вручную.На самом деле это не так уж и сложно, если вы действительно понимаете, как работает подсчет ссылок, и сразу же вызывает проблему, когда вы этого не понимаете.

Если вы точно уверены, какая длина строки вам понадобится, используйте -initWithCapacity:метод.Когда вы превышаете объем хранилища строки, она перераспределяется и копируется, а это недешевая операция.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top