ARC 是否保留对对象的无主引用计数?
那么,如果一个对象的强引用计数达到 0 并且该对象的无主引用计数 > 0,那么该对象被取消初始化但没有被取消分配?并且只有当强引用计数和无主引用计数达到 0 时,它才会被取消分配?
我在一篇文章中读到过,我想是在 Medium 上)但我不确定它是否正确。
最佳答案
首先,让我们意识到这些问题的答案都是我们通常应该避免依赖的实现细节。现在,开始回答:
Is it true that ARC keeps a count of unowned references to an object?
是的,这是真的。每个对象都有三个引用计数:强计数、无主计数和弱计数。
强计数总是被存储(但存储时调整为 -1,因此存储的 0 表示强引用计数为 1,存储的 1 表示强引用计数为 2,依此类推).
unowned 计数也始终被存储,调整 +1 表示所有强引用并在反初始化结束时被删除。
弱引用计数仅在创建对象的第一个弱引用后才存储。弱引用计数,如果存储的话,存储+1调整,代表所有无主引用,在对象被释放后被移除。
So, if the strong reference count of an object reaches 0 and the unowned reference count of that object is > 0 the object is de-initialized but not de-allocated?
正确。对象被取消初始化:对象类和所有父类(super class)的 deinit
运行,对象的任何本身是引用的属性都设置为 nil。但是,对象的内存不会被释放,因为对象的 header 必须保持有效,直到对象的最后一个 unowned
引用被销毁。
And only when the strong and unowned reference count reaches 0 does it get de-allocated?
正确。当强引用计数和无主引用计数都达到零时,对象将被释放。由于大多数对象从未被 unowned
引用引用,这通常是在最后一个强引用被销毁时。
您没有询问弱引用,但为了完整起见,我也会对其进行解释。当一个对象被(或曾经被)弱引用时,Swift 会为该对象分配它所谓的“侧表条目”(或有时只是“侧表”)。
如果对象没有边表,则强计数和无主计数直接存储在对象中,不存储弱计数(必须为零)。
如果一个对象有一个边表,则指向该边表的指针存储在该对象中。强计数、无主计数和弱计数,以及返回对象的指针,存储在侧表中。
对象的弱引用存储为指向边表的指针,而不是指向对象的指针。这意味着即使仍然存在对它的弱引用,一个对象也可以被释放(而不仅仅是取消初始化)。
当对象被释放如果没有对该对象的弱引用时,边表被释放。如果仍然存在弱引用,则对象将被释放,但侧表仍保持分配状态。当对释放对象的最后一个弱引用被销毁时,侧表被释放。
请注意,当 Swift 对象被取消初始化或释放时,弱引用不会立即设置为 nil(销毁)!当程序尝试加载引用时,或者当弱引用的容器被取消初始化时,对反初始化对象的弱引用只会被设置为 nil。 (我所说的“容器”是指,例如,当对象具有 weak var
属性时。该对象是 weak var
引用的容器。)
RefCount.h
in the Swift source code 置顶大评论解释了所有这些细节以及更多内容。
附言还有一种引用,unowned(unsafe)
,它不调整任何引用计数。您应该尽可能避免这种引用(并且几乎总是可以避免)。
关于swift - ARC 是否对无主引用进行计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54836745/