是否有某种程序分析在运行时减少/删除引用计数?或者它们只是“自动”,因为程序员不需要手动递增和递减计数,但只要引用/消失就会发生?
基本上,是什么让ARC与正常的引用计数不同?是否有任何已发表的论文讨论正在发生的事情,特别是如果它正在使用程序分析?
答案 0 :(得分:1)
是否有某种程序分析在运行时减少/删除引用计数?
不,正在进行程序分析,以自动插入维持引用计数的调用。
或者它们只是“自动”,因为程序员不需要手动递增和递减计数......
完全。在ARC之前,Objective-C程序员必须小心地在对象上调用-retain
时要保持对它的引用,并在-release
完成对象的引用时。这些方法递增和递减对象的引用计数。使用ARC,编译器会确定应该添加这些调用的位置并插入它们(或等效代码)。因此,从程序员的角度来看,引用计数是自动的。
答案 1 :(得分:1)
自动引用计数(ARC)在编译时涉及静态分析,但不执行任何运行时分析。
概念化ARC的简单方法是两遍过程。首先,它检查您的代码并在引入对象引用和/或超出范围的位置插入内存管理代码(在语义上等同于ARC ObjC之前的retain
和release
调用)。所以这个:
func doSomething() -> Object {
let thing1 = Object(name: "foo")
var thing2 = Object(name: "bar")
thing2 = Object(name: "baz")
return thing2
}
...变成(在某些编译器内部中间形式中)这样的东西:
func doSomething() -> Object {
let thing1 = Object(name: "foo")
__retain(thing1) // increment reference count so thing1 sticks around
var thing2 = Object(name: "bar")
__retain(thing2) // increment reference count so thing2 sticks around
let oldThing2 = thing2 // thing2 gets replaced on the next line
thing2 = Object(name: "baz")
__release(oldThing2) // get rid of the thing that got overwritten
__retain(thing2) // hold onto the new thing that replaced it
__release(thing1) // end of scope, so nothing else will use thing1
return __autorelease(thing2) // relinquish ownership of thing2,
// but only upon handing ownership over to our caller
}
引入对象引用的时间以及它们超出范围或被传递给调用者的时间(通过return
语句)是从一行到另一行完成程序语义的最低要求,但是停止在此分析级别导致冗余内存管理。 (例如,thing1
在创建之后永远不会被使用。所以ARC做的下一件事就是流量分析以消除冗余并执行其他优化,使我们的示例伪代码更像是这样:
func doSomething() -> Object {
_ = Object(name: "foo") // formerly thing1
// Object.init(name:) is called in case it has side effects,
// but the result is immediately discarded because it's not used
_ = Object(name: "bar") // formerly thing2
// again we call the initializer but discard the result,
// because the original thing2 is immediately overwritten
let thing2 = Object(name: "baz")
// no retain, because nothing happens between here and return
// that could affect the memory lifetime of thing2
return __magic_autorelease(thing2)
// and there's other voodoo we can do to ensure handoff to the caller
// without getting into retain count tracking or autorelease pools
}
这显然是一个非常随意的概述 - 在幕后有更多的内容,所以真正的实现并不完全适合这个简单的两步过程,但从概念上来说它非常相似。有关更详细的讨论,请查看:
前两个是关于Objective-C中的ARC,但是Swift中的ARC是非常密切相关的,所以如果你想知道ARC是如何工作的,最好看看它的ObjC起源。