it-swarm.com.ru

Распределение и инициализация объекта в Задаче C

В чем разница между следующими двумя способами выделения и инициации объекта?

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

а также

self.aController= [[AController alloc] init];

Большая часть примера Apple использует первый метод. Зачем вам выделять, инициализировать и возражать, а затем немедленно освобождать?

56
Ronnie Liew

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

Правильная формулировка последнего будет

self.aController= [[[AController alloc] init] autorelease];

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

Другая "возможная" реализация (в зависимости от того, откуда взят пример) просто:

aController = [[AController alloc] init];

Однако установка переменной экземпляра напрямую не рекомендуется в любом другом месте, кроме как в методах init или dealloc. В другом месте вы всегда должны использовать методы доступа.

Это подводит нас к реализации, показанной в примере кода:

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

Это следует передовой практике, поскольку:

  • Избегает авто-релиза;
  • Это делает семантику управления памятью сразу понятной;
  • Он использует метод доступа для установки переменной экземпляра.
30
mmalc

Если вы используете XCode, он может помочь вам обнаружить такой код с помощью статического анализатора. Просто нажмите Build >> Построить и проанализировать

alt text

Это покажет вам очень полезное сообщение в таких частях кода.

alt text

5
leviathan

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

self.aController = [[[AController alloc] init] autorelease];

Хотя в теории авто-релиз iPhone как-то дороже (никогда не слышал четкого объяснения, почему), и поэтому вы можете явно освободить сразу после назначения объекта в другом месте.

5
Kendall Helmstetter Gelner

Еще одна вещь, на которую следует обратить внимание, это то, что ваш пример зависит также от определения @property aController.

Если он был определен как @property (readwrite, retain) id aController;, тогда ваш пример работает, в то время как если он определен как @property (readwrite, assign) id aController;, то дополнительный вызов release вызовет освобождение вашего объекта.

4
Ashley Clark

Вы могли бы также сделать

@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];

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

2
mk12