2013-06-13 2 views
2

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

Является ли это:

1.

ViewController *tViewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 
self.viewController = tViewController; 
[tViewController release]; 

лучше, чем это:

2.

self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease]; 

Как и почему?

EDIT:

Ok, в первую очередь, я благополучно выпустили все, что я имею в собственности. Я вижу, что это происходит.

Но во втором случае это отсроченный выпуск, так как я могу выяснить, когда он ушел? Это то, что меня смущает autorelease.

Это не единственный экземпляр в программе, где такое может случиться. Когда мне нужен конкретный объект, который я создал, чтобы остаться в живых, пока бог не знает, когда, что мне делать? I autorelease это? Но если он уйдет в неподходящее время? Что мне делать тогда?

+0

Почему вы не используете ARC? – NAZIK

+10

Чтобы эффективно использовать ARC, я хочу сначала изучить Руководство по управлению памятью. – esh

ответ

0

В своих книгах я всегда говорил, что второй способ - лучший. Но в прошлом некоторые люди не соглашались, особенно. на iOS. Какая разница?

  1. Есть ли разница?

Оба варианта выделяют объект. Оба варианта заботятся о его выпуске. («Autorelease является выпуск»). Но они делают это в разные моменты времени:

  1. Вариант: Объект выпущен в конце ARP, по крайней мере, в конце runloop.
  2. Вариант 2: Объект немедленно освобождается release.

(оба: если нет дополнительной ссылки.)

  1. Почему мне нужно -autorelease?

Бывают ситуации, когда release невозможен без нарушения правил MM. Самый простой случай заключается в том, что вы хотите вернуть выделенный объект. Кто должен его отпустить? Способ создания? Это вернет что-то потенциально освобожденное. Метод, который отправил сообщение? Это привело бы к дисбалансу +1 методов, таких как alloc с -1 методами вроде release. Нет выхода.

Пример:

- (NSString*)fullName 
{ 
    NSString *fullName = [[NSString alloc] initWithFormat:@"%@, %@", self.lastName, self.firstName]; 
    return fullName; // Who balance +alloc? 
} 

По autoreleasing объекта, ваш метод остается сбалансированным и может безопасно вернуть объект.

В других случаях это удобный способ избавиться от зависимостей. Представьте себе этот код:

Person *person = …; 
NSString *name = person.name; 
[person release], person=nil; // Imagine that this will dealloc the instance. 
// name is invalid, because person released it. 

С autorelease у вас нет этой проблемы. Существует несколько решений:

Геттер отправляет retain, autorelease в возвращаемое значение. Существует дополнительная ссылка в ARP preventig строку из dealloction:

- (NSString*)name 
{ return [[_name retain] autorelease]; } 

Или тот, кто использует метод делает это:

NSString *name = [[person.name retain] autorelease]; 

Следующая проблема с проблемой с release том, что он труднее использовать return, break или continue:

while (…) 
{ 
    id object = [[Class alloc] …] 
    if (…) 
    { 
     break; 
    } 
    [object release]; 
} 

Там нет никаких проблем с autoreleas е.

Далее: По некоторым причинам рекомендуется использовать распределители удобностей, если они существуют. Объекты, возвращенные оттуда, не могут быть выпущены явно, поэтому код для отказа от ссылки имеет зависимость от того, как была установлена ​​ссылка. Почему бы не использовать autorelease все время?

  1. Что является недостатком autorelease

Удаление объекта потенциально отложено, так что вы можете получить проблемы с объемом памяти.Но я лично считаю, что @autorelease{} - лучшее решение для этого, чем release.

+0

Удобные распределители? Пример? – esh

+0

Я предполагаю, что первая часть вашего ответа была чем-то требуемым, потому что вы нажимали «почему автореферат?». часть моего вопроса. «Сохранение» было особенно важно. Итак, я отдам его тебе. – esh

+0

@ BlackFlam3 Прежде всего: Спасибо. –

1

Оба делают то же самое. Единственное отличие: 1 имеет ссылку [tViewController], чтобы установить экземпляр, а в 2 - напрямую.

3

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

Первая версия выпускает экземпляр сразу после выпуска (детерминированный) - хотя, поскольку self.viewController, вероятно, является сильной ссылкой, экземпляр не будет освобожден от вызова выпуска.

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

+1

(+1) Я только заменил бы «временный экземпляр» на «временную ссылку» в первом предложении. –

+0

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

0

Дело в том, что в первом случае вы вручную запускаете viewController. И он немедленно уничтожился. Во втором случае объект уничтожается в конце цикла события. Иногда, если я выполняю что-то, потребляющее много времени в цикле, в одной функции с большим количеством объектов с автореализацией - я создаю пул авторезистов вручную и сбрасываю его на каждую итерацию.

От NSAutoreleasePool Class Reference:

Комплект приложений создает autorelease пул на главном потоке в начале каждого цикла цикла событий, и стоки его в конце, таким образом высвобождая любые autoreleased объектов, сгенерированных при обработке события.

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