[英]Will an object returned by a method be put into autorelease pool?
当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;
}
启用ARC后,是否将在此代码段中放入自动释放池?
答案是,可能会或可能不会。 ARC均无法保证。 在这里,方法的名称( obj
)并非以表示保留的返回类型的特殊名称之一开头(例如alloc
, retain
, new
, copy
, mutableCopy
),因此它返回一个非保留的引用。 关于“未保留的返回值”的ARC规范部分说:
在最坏的情况下,这可能涉及自动释放,但是调用者不得假定该值实际上在自动释放池中。
在过去,根据MRC,在这种情况下,您必须先autorelease
它,然后再返回,因为要求该方法返回一个非保留的引用,但是有人必须持有对该对象的强引用,否则它将被释放。 。 由于对象是在您的方法中创建的,因此没有其他人对其进行引用,并且该方法必须在其作用域的末尾摆脱其强引用,因为它无法返回保留的引用,因此唯一的方法是拥有自动释放池在返回中具有很强的参考价值。
ARC必须保持与MRC的ABI兼容(即,您应该能够用ARC替换MRC实施,反之亦然,而无需更改标头,并且调用者不需要知道它是使用ARC还是MRC编译的即可正常工作)。 因此,在从MRC代码调用您的方法的情况下,按照与上一段相同的逻辑,您的方法必须autorelease
; 根本没有其他方法可以做到。
但是,ARC引入了聪明的可选运行时优化,在某些情况下,当调用方和被调用方都使用ARC编译时,它可以消除autorelease
,而调用方或被调用方无需了解另一端。 大概是这样工作的:在通常会autorelease
功能的函数的返回中,ARC而是调用objc_autoreleaseReturnValue()
。 在调用函数并保留返回值的代码中,它改为调用objc_retainAutoreleasedReturnValue()
。 在objc_autoreleaseReturnValue()
,它在堆栈框架上查找返回地址,以查看是否将返回值传递给objc_retainAutoreleasedReturnValue()
。 如果没有,它将autorelease
。 如果是,那么它会跳过autorelease
,并修改返回地址跳过objc_retainAutoreleasedReturnValue
,从而消除两者的autorelease
和retain
,这抵消了。 在objc_retainAutoreleasedReturnValue()
,如果不跳过它,它将retain
。 这对于MRC-to-ARC调用,ARC-to-ARC调用和ARC-to-MRC调用正确运行,并且会消除某些ARC-ARC调用的autorelease
。
而且,这两个代码段之间有什么区别?
第一个可能会将其放入自动释放池,而第二个可能不会。 (顺便说一下, __strong
是默认值,因此第三部分代码与第一部分相同。)
但是基本上没有充分的理由对局部变量使用__autoreleasing
而不是默认变量( __strong
)。 __strong
更容易思考。
通常,您遇到__autoreleasing
的唯一时间是参数的“指针指向”类型-如果函数声明它需要指向__autoreleasing
的指针(例如NSObject * __autoreleasing *
),则意味着它将写入指向指针的变量与采用指向__strong
的指针的方式__strong
(例如NSObject * __strong *
)。 两种方法都可以,但是主叫方和被叫方需要就哪种方法达成共识。 由于可可中普遍使用NSError * __autoreleasing *
,因此不合格的默认指向__autoreleasing
指针(例如, NSObject **
表示NSObject * __autoreleasing *
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.