0

Когда ARC включен, будет ли o помещен в пул автономии в этом фрагменте кода?Будет ли объект, возвращенный методом, помещаться в пул авторесурсов?

- (NSObject *)obj { 
    NSObject *o = [[NSObject alloc] init]; 

    return o; 
} 

Более того, в чем разница между этими двумя фрагментами кода?

- (NSObject *)obj { 
    NSObject * __autoreleasing o = [[NSObject alloc] init]; 

    return o; 
} 

против

- (NSObject *)obj { 
    NSObject * __strong o = [[NSObject alloc] init]; 

    return o; 
} 
+0

Ответ на первый вопрос: Да. Просто все равно. – dasdom

ответ

5

Когда ARC включена, то будет о быть введен в autorelease пул в этом коде фрагмент кода?

Ответ может быть, может быть, или нет. ARC не дает гарантии в любом случае. Здесь имя метода (obj) не начинается с одного из специальных имен, которые указывают на сохраненный тип возврата (например, alloc, retain, new, copy, mutableCopy), поэтому он возвращает не сохраненную ссылку. ARC specification section on "Unretained return values" говорит:

В худшем случае это может повлечь за собой autorelease, но абоненты должны не считать, что значение на самом деле в autorelease бассейне.

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

ARC должен оставаться совместимым с ABI с MRC (то есть вы должны иметь возможность заменить реализацию MRC с помощью ARC или наоборот, без изменения заголовков и вызывающих абонентов не нужно знать, была ли она скомпилирована с ARC или MRC работайте правильно). Поэтому в случае, когда ваш метод вызывается из кода MRC, следуя той же логике, что и в предыдущем абзаце, ваш метод должен быть autorelease; просто нет другого способа сделать это.

Однако ARC представляет собой умную опциональную оптимизацию времени выполнения, которая может устранить autorelease в некоторых случаях, когда вызывающий и вызываемый команды скомпилированы с помощью ARC, без вызова вызывающего абонента или вызывающего абонента, который должен знать о другой стороне. Это примерно так, как это работает: при возврате функции, где вы обычно бывали autorelease, ARC вместо этого звонит objc_autoreleaseReturnValue(). И в коде, который вызывает функцию и сохраняет возвращаемое значение, вместо этого он вызывает objc_retainAutoreleasedReturnValue(). В objc_autoreleaseReturnValue() он обращается к обратному адресу до кадра стека, чтобы узнать, будет ли возвращенное значение передано objc_retainAutoreleasedReturnValue(). Если нет, то это будет autorelease. Если это так, то он пропустит autorelease, а также изменит адрес возврата, чтобы пропустить objc_retainAutoreleasedReturnValue, таким образом удалив как autorelease, так и retain, что отменяет. В objc_retainAutoreleasedReturnValue(), если он не пропущен, он будет только retain. Это корректно работает для вызовов MRC-ARC, вызовов ARC-ARC и вызовов ARC-to-MRC и устраняет autorelease для некоторых вызовов ARC-ARC.


Более того, в чем разница между этими двумя фрагментами кода?

Первый будет помещен в пул авторефератов, а второй - нет. (Кстати, __strong по умолчанию, так что третья часть кода идентична первой.)

Но нет, по существу, нет веских причин использовать __autoreleasing для локальной переменной вместо значения по умолчанию (который __strong) ; __strong проще и проще думать.

Обычно единственный раз, когда вы столкнетесь с __autoreleasing в «указатель на» типы в параметрах - если функция объявляет, что оно принимает указатель на __autoreleasing (например NSObject * __autoreleasing *), это означает, что он будет писать в указываемом переменная по-другому, чем если она принимает указатель на __strong (например, NSObject * __strong *). Оба способа работают, но вызывающий и вызывающий должны согласовать, какой из них. Из-за вездесущего использования NSError * __autoreleasing * в какао неквалифицированный по умолчанию указатель на __autoreleasing (например, NSObject ** означает NSObject * __autoreleasing *).

+0

Ваш ответ очень ясен. Спасибо! – SamirChen

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