【问题标题】:When is `deinit` exactly called? (in Swift)什么时候准确地调用了`deinit`? (在斯威夫特)
【发布时间】:2021-10-14 06:22:44
【问题描述】:

deinit 的准确调用时间是什么时候?

当最后一个引用超出范围(通过返回、抛出或退出)时,是否保证调用 C++?

或者Swift 正在使用垃圾收集器?

【问题讨论】:

标签: swift automatic-ref-counting destructor dealloc deinit


【解决方案1】:

你问:

deinit 何时调用?

简而言之,对于引用类型,当最后一个强引用被移除时,对象会被取消初始化。

因此,它通常不是任何特定变量的问题,而是所有引用的问题,并且在最后一个强引用被删除时,就在它被释放之前,它被取消初始化。请参阅 Swift 编程语言, Deinitialization 和 Automatic Reference Counting。

然后你问:

还是 Swift 使用垃圾收集器?

Swift 不使用垃圾回收。曾经有垃圾收集(在早期的 Objective-C 时代,用于 macOS 目标),但它早已被弃用并被引用计数系统所取代,后来随着 ARC(自动引用计数)的引入而简化。但是 Swift 从来没有实现过垃圾回收。

【讨论】:

  • 编辑了我的答案并应用了我们的 cmets(我想,可能在你在这里发帖之前一点点),但是当我接受这个答案时,我实际上是在接受你的建议(如果它提到我会直接接受这个autorelease-pool 和其他详细信息)。
【解决方案2】:

deinit 旨在释放资源(例如释放不在 ARC 下的内存)。

(感谢Martin 和Rob的输入,我们可以在下面得出结论)

deinit 何时调用?

通常,当最后一个强引用超出范围时, deinit 被立即调用(然后释放)。

  • 但如果受到autorelease 功能的影响, deinit 会显着延迟调用, 在最后一个引用超出范围后很久(当autorelease 池被耗尽时)。
  • 当应用程序终止时,deinit 保证永远不会被调用!? (如果尚未调用 deinit)。
  • 同样在极其常见的情况下,deinit 在 strong-ref-variable 的作用域结束之前被调用:
    • 在 Swift 中与其他语言不同,当我们将弱引用设置为等于强引用时, 它可能会导致nil(Swift 绝对允许)。

    • 如果编译器检测到剩余的范围行,就会发生这种情况, 没有任何强引用。

    • 可能的解决方法是使用withExtendedLifetime(_:_:) global-method,例如:

    withExtendedLifetime(myStrongRefVariable) {
         // Do something that only needs non-nil weak reference.
    }
    

是不是像C++析构函数?

在ObjC 或Swift 中没有等效的C++ 析构函数。

(Objective-C++ 对象的析构函数在程序终止期间被调用, 因为这是C++ 规范所要求的, 但仅此而已,并且 Obj-C++ 的 dealloc 行为与 deinit 相同。)

Swift 是否使用垃圾收集器?

不,但每当autorelease 功能影响对象时, deinit 可以推迟(直到 autorelease-pool 耗尽,如上所述)。

【讨论】:

  • 我发现您的回答有点令人困惑和误导。 deinit is 在不再存在对对象的引用时立即调用(就在对象释放之前)。 – “Swift 可能将强引用变量设置为 nil”到底是什么意思?
  • “但在 GC 释放之前” – Swift 使用 ARC(自动引用计数)。没有垃圾收集器。
  • (Java) 垃圾回收和 (Swift, ObjC) ARC 是完全不同的内存管理机制。
  • 是的,尽管自动释放对象在 Swift 项目中越来越少见(尽管有时它们由旧的 ObjC 库提供)。在极少数情况下,您确实有一个自动释放对象,当自动释放池耗尽时,该特定引用会被解析(例如,您返回给操作系统,或者如果您使用自己的自动释放池)。
猜你喜欢
  • 2017-07-22
  • 2017-03-24
  • 2015-04-07
  • 1970-01-01
  • 2016-09-19
  • 1970-01-01
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多