迅速。无主的(绝对)唯一的特定优势是弱性能吗?

Posted

技术标签:

【中文标题】迅速。无主的(绝对)唯一的特定优势是弱性能吗?【英文标题】:Swift. Is the (absolutely) sole specific advantage of unowned over weak, performance? 【发布时间】:2017-01-24 14:25:13 【问题描述】:

在 Swift 中,我们有正常的默认类型

对象根本不可能变成 nil。

我们的打字很弱

对象可以变为 nil。如果对象变成 nil,你的指针会自动变成 nil,所以你知道对象变成了 nil

我们有无主的打字

对象可以变为 nil。如果对象变为 nil,则指针不会发生任何事情 - 如果您尝试使用它,您会被搞砸

(因此:推论:你可以使用“unowned”的唯一一次是如果你“绝对知道”该对象将永远不会变为 nil。)

现在:

在我看来,下面这句话,

绝对真的...

我的意思是,真的,真的,绝对,直到最深层次的哲学问题真的......

“unowned 和weak 的唯一区别是性能。由于unowned 没有检查,所以速度更快。绝对没有其他区别。”

因此逻辑推论:

“有,绝对,没有理由使用 unowned,除非需要额外的弱性能。”

除此之外 - 我能想到的唯一其他区别是在自我记录的意义上。如果我使用 unowned,它会提示我的其他开发人员注意某些事情;让我们暂时搁置这个问题。)

所以我的问题是直截了当、非常准确、非常具体的:“真实”上方的粗体句子是真实的吗(在“完全、非常、壮观”的真实意义上)。

【问题讨论】:

不必每次都打开包装,这不是很大的不同吗? 对,无主变量不是可选的,因此您可以避免麻烦。 @JamesP - 这可能是一个突出的点;也许一个有启发性的例子的答案可能是有序的? 【参考方案1】:

我同意亚尼克的观点。你的粗体陈述是不正确的。无主引用必须在其生命周期内有效。在-Ounchecked 程序中,未能维护此前提条件是未定义的行为。我的意思不是“它崩溃了”。我的意思是它不是一个格式良好的程序。它的作用是不确定的。弱引用由于其发布而无法生成未定义的行为,即使在-Ounchecked 下也是如此。

使用unowned程序员声明的引用将在其整个生命周期内有效。这甚至不是Type! 断言的东西。 ! 类型只是断言引用在访问时将是有效的。这就是为什么您不能在无主对象上测试 x == nil 的原因。这不是可选的。它不是“变相可选”(如Type!)。它必须始终有效。

然而,与弱引用不同的是,当另一个实例具有相同的生命周期或更长的生命周期时,将使用无主引用。 ... 一个无主引用应该总是有一个值。 —— [The Swift Programming Language]

因此,对于您的“最深层次的哲学”,无主包括一个不存在于弱中的先决条件。这个前提条件存在于程序之外,必须由程序员而不是编译器证明,以确保程序结构良好。

是否有理由使用unowned,如果我们采取绝对立场(如您的问题),那肯定是有理由的。在已知前提条件为真的情况下,它是最严格的类型。 weak 是比unowned 弱的类型;它表达的先决条件较少。好的类型理论鼓励我们尽可能使用最强(限制性最强;合法值最少)的类型,unowned 是比weak 更强的类型。

在非绝对主义(“实用”)意义上,选择更强类型的结果是更简单的代码。当您使用weak 时,您必须在每次使用它时不断重新断言它不是nil 的前提条件并处理它的情况(可能插入fatalError,它只是通过更多工作重新发明unowned )。使用unowned 可以让您一次性断言此前提条件。这会创建更简单、更正确的代码。我从来没有使用unowned 来提高速度。我一直用它来避免一遍又一遍地回答“但如果它是零怎么办?”在代码中它绝不能为零。

【讨论】:

这是一个深刻的想法,无主是更强 ...很好。太棒了。 “我一直使用它来避免一遍又一遍地回答“但是如果它是 nil 怎么办?”在代码中它决不能是 nil。我认为,这很有见地,真正回答了问题的“核心”。【参考方案2】:

粗体句子不正确

Weak 是可选的,可以随时设置。

Unowned 是非可选的,但可以为零。如果发生这种情况并且你称之为你的应用程序崩溃。必须在初始化时设置。

正如作者所说,另一个区别是性能。 Unowned 不做任何检查,比weak 稍快。

更好地展示了类之间的关系。

您可以查看此 SO 问题以了解更多详细信息:What is the difference between a weak reference and an unowned reference?

【讨论】:

Unowned 表面上是非可选的,但它可能会突然变为 nil(或无效指针,更好的措辞),如果使用不当会破坏您的应用程序。 是的,但我不想在这里详细介绍。发布的链接更详细地介绍了这一点,而且作者自己也说过。 嘿@Yannick - 谢谢你;我倾向于说“但除此之外还有什么不同吗”:)这可能不符合我的问题的精神:) 嗨@user28434 - 是的,当然:这就是问题的重点。显然无主可以通过悬空下地狱:我的问题,除了纯粹的性能之外还有任何优势吗? @JoeBlow,性能提升很小 + 非可选“接口”,例如 T!T?【参考方案3】:

来自快速文档

"Swift 还为您在以下情况下提供了不安全的无主引用 需要禁用运行时安全检查——例如,为了性能 原因。与所有不安全的操作一样,您承担责任 用于检查该代码的安全性。

你通过写 unowned(unsafe) 来表示一个不安全的无主引用。 如果您尝试在实例之后访问不安全的无主引用 它所指的已被释放,您的程序将尝试访问 实例曾经所在的内存位置,这是不安全的 操作。”

似乎只有当您准确地使用 unowned(unsafe) 并且默认情况下我们使用 unowed(safe) 时才能获得性能提升。

This is from one of the answer

unowned(safe) 是一个非拥有引用,它在访问时断言 对象还活着。这有点像一个弱可选参考 这是用 x 隐式展开的!每次访问它。 unowned(unsafe) 就像 ARC 中的 __unsafe_unretained — 它是非拥有的 参考,但没有运行时检查对象是否仍然存在 在访问时,因此悬空引用将进入垃圾内存。 当前,unowned 始终是 unowned(safe) 的同义词,但是 意图是它将在 -Ofast 中优化为无主(不安全) 在禁用运行时检查时构建。

【讨论】:

以上是关于迅速。无主的(绝对)唯一的特定优势是弱性能吗?的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB中唯一索引的优势

快速无主的安全

高并发下唯一 ID 生成方案

MySQL 常用SQL查询语句

MySQL 常用SQL查询语句

MySQL 常用SQL查询语句