Не смертельно ли использовать __autoreleasing?

from: В каких ситуациях нам нужно написать квалификатор владения __autoreleasing под ARC?

  • (BOOL) save: (NSError * __autoreleasing *);

Затем компилятор должен будет создать временную переменную, установленную в __autoreleasing. Так:

NSError * e = nil;
[ database save: &error ];

Будет преобразовано в:

NSError __strong * error = nil;
NSError __autoreleasing * tmpError = error;
[ database save: &tmpError ];
error = tmpError;

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

Чтобы быть более точным. Я понимаю, что мы "должны" использовать __autoreleasing когда мы передаем указатель на указатель. Однако, если единственное, что мы получили, это просто очень небольшое увеличение производительности, то какой в ​​этом смысл?

1 ответ

Вам не хватает того, что на самом деле происходит в этом коде, когда переменная передается по ссылке и присваивается в программе ARC.

В программировании без ARC функция сохранения выглядит следующим образом:

- (BOOL)save:(NSError * __autoreleasing *)myError {
  *myError = [[[NSError error] retain] autorelease]
}

В программировании ARC функция сохранения выглядит следующим образом:

- (BOOL)save:(NSError * __autoreleasing *)myError {
  *myError = [[NSError alloc] init];
}

Несмотря на то, как выглядит код ARC, обе функции сохранения создают объект ошибки, который был сохранен и автоматически освобожден.

Это связано с тем, что в версии ARC тип указателя myError определяет, что происходит с управлением памятью объекта ошибки. В действительности, пока указатель имеет тип __autoreleasing, строка назначения *myError заменяется на

*myError = [[[NSError error] retain] autorelease]

во время выполнения.

Так что, если бы мы могли каким-то образом передать указатель неправильного типа в функцию сохранения, это заставило бы функцию сохранения делать неправильные вещи.

Поскольку компилятор создаст временную переменную в вашем примере, ваш код будет работать в любом случае, но первая версия не имеет смысла с точки зрения программирования ARC.

Другие вопросы по тегам