NSMutableArray -init против + arrayWithCapacity:

У меня есть две функции, которые я должен использовать? Пожалуйста, объясните разницу.

А:

- (NSMutableArray *)FunctionA:(int)count {

    NSMutableArray *a = [[NSMutableArray alloc] init];

 for (int i = 0; i < count; i++) {
  [a addObject:[NSNumber numberWithInt:0] ];
    }

    return [a autorelease];
}

B:

-(NSMutableArray *)FunctionB:(int)count {

 NSMutableArray *b = [NSMutableArray arrayWithCapacity:count];

 for (int i=0;i<count; i++){  
  [b addObject:[NSNumber numberWithInt:0] ];  
 }

 return b;  //  or [b autorelease] ?
}

Ответ 1

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

Второй дает массиву подсказку (вам, вероятно, понадобится "эта много" комната), чтобы избежать накладных расходов на увеличение массива при добавлении известного количества объектов. Конечно, он по-прежнему будет расти, если потребуется (как будто вы не указали емкость). Вы должны использовать этот подход, если вы уже знаете счет заранее. Это быстрее с большим количеством.

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

Кроме того, вы не авторизуете B (как вы прокомментировали), потому что вы не создали изменяемый массив с init - вы использовали метод удобства, который сделал это сам, а это означает, что вы не отвечаете за его освобождение. Как я уже упоминал в другом ответе на ваш вопрос, вы также можете создать массив с помощью

[[NSMutableArray alloc] initWithCapacity:capacity];

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

Помните, что: сначала измерьте, затем оптимизируйте, если необходимо.

Ответ 2

Переменные объекты по-прежнему должны выделять пространство, чтобы выделить сумму по умолчанию для 10 объектов. Если вы добавите 11-й, изменяемый массив должен будет выделить новую память, скопировать элементы в новую память и освободить старую память.

Это обычно так быстро, что вы даже не заметите, но это может замедлить его. Создание измененного массива с размером сначала создает массив указанного размера, поэтому, надеюсь, будет меньше изменений размера.

Ответ 3

В первом примере вы должны управлять памятью массива, так как вы создаете его с помощью +alloc и -init (поэтому вам нужно отправить -autorelease на него).

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

Если вы хотите вернуть автореализованный массив, второй вариант, вероятно, будет более предпочтительным, так как +arrayWithCapacity: вернет уже автореализованный массив. Кроме того, поскольку возвращаемый вам массив уже автореализован, вам не нужно отправлять ему -autorelease.

Если у вас еще есть проблемы с управлением памятью, необходимо прочитать "Apple " Руководство по управлению памятью".

Ответ 4

Я бы использовал B:

Плюсы, которые я вижу с ним,

  • Массив не будет нуждаться в изменении размера по мере его увеличения
  • arrayWithCapacity: autoreleases для вас, поэтому вам это не нужно, это улучшает читаемость кода imho

Я надеюсь, что это поможет.