autorelease 用于返回的函数对象,因此调用者不会获得所有权,被调用者将在未来释放该对象。
然而,ARC 能够计算调用者的所有权并在使用后释放它,也就是说,它的行为就像 C++ 中的智能指针。使用 ARC,它可以摆脱自动释放,因为自动释放是不确定的。
我问这个问题的原因是我确实看到返回的对象在 ARC 中比在非 ARC 代码中调用 dealloc 更早。这使我认为 ARC 可以像智能指针一样运行并且可以使自动释放无用。这是真的还是可能的?我唯一能想到的自动释放有用性是在多线程或网络代码中,因为当对象传递时计算所有权可能并不容易。
谢谢你的想法。
这里是新的编辑来澄清:
自动释放
+ (MyClass*) myClass
{
return [[[MyCClass alloc] init] autorelease];
}
- doSomething
{
MyClass *obj = [MyClass myClass];
}
使用 ARC:
+ (MyClass*) myClass
{
return [[MyCClass alloc] init]; // no autorelease
}
- doSomething
{
MyClass *obj = [MyClass myClass];
// insert [obj release]
}
所以,我们真的不需要自动释放。
最佳答案
自动释放作为一种机制仍然被 ARC 使用,此外,ARC 编译代码旨在与 MRC 编译代码无缝互操作,因此自动释放机制就在身边。
首先,不要从引用计数的角度考虑,而是从所有权利益的角度考虑——只要一个对象声明了所有权利益,那么该对象就会存在,当没有所有权利益时,它就会被销毁。在 MRC 中,您可以通过使用 retain
或通过创建新对象来声明所有权权益;并使用 release
放弃所有权权益。
现在,当被调用方方法创建一个对象并希望将其返回给调用方时,被调用方将离开,因此它需要放弃所有权权益,因此调用方需要声明其所有权权益,否则该对象可能会被销毁。但是有一个问题,被调用者在调用者接收到对象之前完成 - 所以当调用者放弃其所有权权益时,对象可能在调用者有机会声明其权益之前被销毁 - 这不好。
有两种解决方案可以解决这个问题:
1) 声明该方法以转移其返回值的所有权权益从被调用方到调用方 - 这是用于init
、copy 的模型
等方法。被调用者从不通知它正在放弃其所有权权益,并且被调用者从不声明所有权权益 - 通过协议(protocol),调用者只是接管所有权权益和稍后放弃它的责任。
2) 该方法被声明为返回一个值,其中调用者没有所有权权益,但其他人将在短时间内保持所有权权益 - 通常直到当前运行循环周期结束。 如果调用者想要使用返回值的时间比这更长,则必须声明其自己的所有权权益,否则它可以依赖拥有所有权权益的其他人,因此该对象会保留下来。
问题是,谁能成为维护所有权权益的“人”?它不能是被调用方方法,因为它即将消失。输入“autorelease pool”——这只是一个对象,任何人都可以将所有权权益转让给该对象,因此该对象将保留一段时间。自动释放池将在收到指示时放弃其对以这种方式转移给它的所有对象的所有权权益——通常是在当前运行循环周期结束时。
现在,如果上面的内容有任何意义(即如果我解释清楚的话),您会发现实际上并不需要方法 (2),因为您始终可以使用方法 (1); 但是,这是一个关键的但是,在 MRC 下,程序员需要做更多的工作——从方法接收到的每个值都带有所有权权益,必须对其进行管理和在某个时候放弃 - 生成一个字符串只是为了输出它?好吧,然后您需要放弃对那个临时字符串的兴趣……所以 (2) 让生活变得更轻松。
另一方面,计算机只是快速的白痴,代表智能程序员计算事物并插入代码以放弃所有权权益是它们非常适合的事情。所以 ARC 不需要自动释放池。但它可以使事情变得更简单、更高效,并且在幕后 ARC 优化了它的使用——看看 Xcode 中的汇编器输出,你会看到对名称类似于“retainAutoreleasedReturnValue”的例程的调用...
所以你是对的,它不是需要,但它仍然有用 - 但在 ARC 下你可以(通常)忘记它甚至存在。
HTH 可能比它更令人困惑!
关于ios - ARC 和自动释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17601274/