swift - ARC 是否对无主引用进行计数?

标签 swift automatic-ref-counting strong-references unowned-references

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/

相关文章:

objective-c - 在带有ARC的Objective-C中,我们通常只需要指定nonatomic作为property属性是真的吗?

ios - 启用 ARC 时 NSXMLParser 抛出 EXC_BAD_ACCESS

objective-c - 如何测试 Objective-C 对象是否可以在 ARC 下使用弱引用?

ios - 将强引用转换为对 self 的弱引用

ios - iOS 中的 self.timer = nil 与 [self.timer invalidate] 有什么区别?

swift - 如何在swift中传递可变参数?

ios - SwiftUI:带有 TextView 的混合模式使重叠区域变为白色,其余区域变为黑色

linux - 没有 NSURLRequest 的 Swift 中的 HTTP 请求

swift - 无法在 Swift 中扩展闭包?

Swift 弱引用比强引用慢得多