1

Когда я начал с OSX/прошивкой я использовалразница между литералами и методами класса для NSMutableArray и NSMutableDictionary

NSMutableArray *  a1 = [NSMutableArray arrayWithCapacity:123] ; 
    NSMutableDictionary * d1 = [NSMutableDictionary dictionaryWithCapacity:123] ; 

Тогда я открыл «простую» версию

NSMutableArray *  a2 = [NSMutableArray array] ; 
    NSMutableDictionary * d2 = [NSMutableDictionary dictionary] ; 

Я теперь переехал в:

NSMutableArray *  a3 = [@[] mutableCopy] ; 
    NSMutableDictionary * d3 = [@{} mutableCopy] ; 

Функционально все они кажутся идентичными: после инициализации в любом случае они могут использоваться независимо от того, как они были созданы. Где отличия?

В частности, следует ли считать, что d3/a3 более похожи на d2/a2, чем d1/a1, в терминах предопределения памяти (или их отсутствия)?

Или это только вопрос стиля?

+3

Третий строит неперемещаемый объект и копирует его, создавая какое-то потраченное впустую движение. Это потраченное впустую движение отсутствует в первых двух. Разница между первым и вторым заключается в том, указан ли начальный размер или дефолт. Я не вижу реального смысла в третьем - даже я не * * ленивый. –

+2

Вы также можете просто вызвать new для создания экземпляра. – uchuugaka

+1

@HotLicks, насколько вы уверены в фактической стоимости? По определению NSArray неизменен после создания, что означает, что каждый экземпляр @ [] должен быть isEqual.Это, в свою очередь, означает, что очень дешевая оптимизация компилятором/временем выполнения должна иметь точно один экземпляр @ [] независимо от того, как часто в коде появляются либо @ [] или [NSArray array], либо [NSArray new]. Как бы вы решили проверить, что я ошибаюсь? – verec

ответ

2

Форма первая - это метод фабрики класса, который является оптимизацией, полезной, когда вы знаете, насколько изначально должна быть коллекция, или вы знаете, что размер будет постоянным, но контент может измениться.

Форма 2 - метод фабричного класса, эквивалентный вызову new. Это может быть или не быть таким же, как alloc, за которым следует init, но фактически тот же.

Форма три неявно совпадает с именем, за которым следует initWithArray: или initWithDictionary: соответственно. Это удобно, но генерирует ненужный неизменяемый экземпляр, который отбрасывается в ARC, может быть неясно, когда он отбрасывается.

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

1

a1/d1 выделяются с достаточным начальным пространством для 123 записей.

a2/d2 выделяются с достаточным начальным пространством для 5 записей.

Если вы знаете, что собираетесь добавить кучу записей, a1/d1 более эффективны, потому что словарю не нужно будет выделять больше памяти для хранения все большего количества записей.

a3/d2 ближе к a2/d2, но они на самом деле так же, как:

NSMutableArray *a4 = [[NSArray array] mutableCopy]; 

Это менее эффективно, чем а2.

+1

b.t.w. как вы знаете, что значение по умолчанию a2/d2 - это «5» записей? заключается в том, что в документах Apple или их источниках с открытым исходным кодом? –

+1

Хороший вопрос. Это то, о чем я думал, но я просто проверил документы, и я не могу найти упоминания об этой емкости по умолчанию. Я помню, что это то, что я читал, когда я впервые начал разработку iOS почти 5 лет назад. – rmaddy

+1

Я подозреваю, что начальный размер основан на количестве пространства, оставшегося в «круглом» распределении после всех служебных данных заголовка. Я предполагаю, что они попытаются сделать это в районе 10-15. В любом случае накладные расходы для выделения большего количества записей, вероятно, намного меньше, чем дополнительные затраты на создание объектов версии 3. Учитывая, что часто используются NSMutableArrays, накладные расходы на выделение большего количества записей обычно тривиальны в сравнении. –

1

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

Смежные вопросы