освободить и сохранить - PullRequest
0 голосов
/ 06 марта 2010

Допустим, я делаю следующее (foo начинается как некоторый объект):

[foo release];
// STUFF with foo   
[foo retain];

Пока я не переназначаю foo, в конце этого у меня будет тот же foo, верно? Я не рискую потерять фу во время // ПЕРЕНОСА, не так ли?

Полагаю, я уверен, что мое понимание освобождения правильное. Если я отпущу foo, он на самом деле не исчезнет, ​​пока не исчезнут все его ручки. Другими словами, foo должен был бы быть назначен какому-либо другому объекту в // STUFF, или foo должен был бы выйти из области видимости в // STUFF (и предположительно иметь новый созданный foo) для фактического исходного foo удаляемый объект, верно?

РЕДАКТИРОВАТЬ для мотивации:

Причина, по которой я хочу это сделать, состоит в том, что, скажем, у меня есть следующий оператор switch:

switch (test)
{
   case 1:
      foo = [A alloc];
      [foo inita];
      break;
   case 2:
      foo =  [B alloc];
      [foo initb];
      break;
   case 3: 
      [foo setupc];
      break;
   case 4:
      f = [D alloc];
      [foo initd];
      break;
}

Имеет смысл освободить foo перед переключателем и сохранить его в конце. За исключением случая 3. Итак, я подумал, что если бы было безопасно делать то, что я предложил, это могло бы упростить код.

Конечно, я могу просто поместить пару релиз / сохранение вокруг каждого alloc / init, но это много повторяющегося кода ...

A [foo autorelease], а затем сохранение может просто сделать трюк.

Ответы [ 4 ]

3 голосов
/ 06 марта 2010

Нет, вот что происходит:

Метод -release уменьшает счетчик сохраняемых данных, а затем проверяет, равен ли он нулю. Если счет сохранения равен нулю, -release вызывает [self dealloc], что приводит к немедленному освобождению объекта. Поэтому отправка -release перед отправкой -retain сообщения не будет хорошей идеей для вашего примера и может привести к сбою приложения.

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

Class class = Nil;

// Decide which class (if any) to use...
switch (test)
{
    case 1: class = [A class];  break;
    case 2: class = [B class];  break;
    case 3: class = foo == nil ? Nil : [C class]; break;
    case 4: class = [D class];  break;
}

// If a class was selected, create a new instance 
// and release the previous one...
if (class != Nil)
{
    [foo release];
    foo = [[class alloc] init];
}

Обратите внимание, что здесь нет необходимости в -retain, потому что, как я уже упоминал ранее, +alloc устанавливает счет удержания равным единице.

3 голосов
/ 06 марта 2010

Если в начале этого кода значение сохранения foo обнуляется, оно стирается и перестает работать. Используйте autorelease, если вы хотите сделать что-то подобное. release - это запрет на сборку мусора, согласно документам - может быть, это то, что вы думаете?

0 голосов
/ 06 марта 2010

Да, вы наиболее определенно рискуете "потерять" во время STUFF в среде с подсчетом ссылок (не GC). Если ваш первый -release уменьшит счетчик ссылок foo до 0, он будет освобожден. Продолжение использования foo в этом случае приводит к неопределенному поведению, и вы почти наверняка заплатите цену в конце концов. Другими словами, здесь будут драконы. может работать в том случае, если вы (и любые другие вызываемые вами структуры) не выделяете память во время STUFF, которая переопределяет выделенный экземпляр, на который foo ссылаются и экземпляр, на который указывает foo метод -dealloc, не изменяет состояние foo, за исключением освобождения ссылки на переменную экземпляра, и разбивает память, занятую этими ссылками, и так далее. В этом случае ваш код может работать так, как если бы foo не был освобожден, но это только удача.

В среде сбора мусора вы в безопасности. Поскольку вы держите ссылку на foo - STUFF и поскольку -release и -retain не используются в среде GC, foo все равно будет действительным.

0 голосов
/ 06 марта 2010

Все, что делает release, уменьшает счетчик ссылок, который есть у каждого объекта.

Я не уверен, почему вы хотите release и retain, как вы показали, однако.

...