Является ли автовыпуск возврата ошибкой в ​​​​задаче c?

Я новичок в target c и пытаюсь понять, как/когда вызывается автовыпуск. Я понимаю простой вариант использования:

- (void) foo {
    Bar *b = [[[Bar alloc] init] autorelease];
    [self doSomething:b];
  }

Как насчет следующего случая? Является ли это ошибкой, потому что объект будет немедленно освобожден после выхода из области действия makeBar?

-(Bar*) makeBar
{
    return [[[Bar alloc] init] autorelease];
}

Что, если звонящий делает удержание?

Bar *b = [[self makeBar] retain];

Спасибо, -Эрик


person esilver    schedule 17.02.2010    source источник
comment
Это содержание этого вопроса и два ответа ниже должны быть в обязательном списке для чтения для тех, кто плохо знаком с ObjC.   -  person ckhan    schedule 29.08.2012


Ответы (2)


Во втором примере возвращаемый вами анонимный объект не будет выпущен, как только выполнение покинет область makeBar, но на следующей итерации цикла выполнения. Это даст вам возможность retain использовать любой метод, вызвавший makeBar

Итак, ваш последний пример в порядке, так как количество сохранений не упадет ниже 0.

У вас проблемы с этим?

person Tom Duckering    schedule 17.02.2010
comment
Чтобы быть более конкретным, он будет выпущен, когда пул автоматического выпуска, в который он был добавлен, будет слит/освобожден. Обычно это происходит в конце цикла выполнения, но не всегда. - person dreamlax; 17.02.2010
comment
Нет проблем, я только что сканировал свой код на наличие потенциальных проблем с памятью и увидел шаблон из примера кода, который я скопировал, и не был уверен, ошибка это или нет. - person esilver; 18.02.2010

-(Bar*) makeBar
{
    return [[[Bar alloc] init] autorelease];
}

Второй случай является предпочтительным способом возврата объекта Objective-C. За исключением +alloc, -copy... и -create..., метод не должен сохранять права собственности на возвращаемый объект, т. е. счетчик сохранения (изменения) должен быть равен 0.

Однако [[Bar alloc] init] заставляет объект сохранять значение +1, чтобы его нужно было освободить перед возвратом. Но -release немедленно освободит объект, что сделает метод бесполезным. Вот почему используется -autorelease — это отложенный -release, т. е. объект будет выпущен в конце концов, но не сейчас, поэтому другие части кода все еще могут взаимодействовать с ним, но количество сохранений все еще может быть сбалансировано. до 0.


Bar *b = [[self makeBar] retain];

Вам не следует не сохранять его, если только вы не хотите быть долгосрочным владельцем объекта b.

person kennytm    schedule 17.02.2010