Не смертельно ли использовать __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.