弱引用和无引用引用之间有什么区别?

Ian*_*ose 232 memory-management weak-references automatic-ref-counting dangling-pointer swift

斯威夫特有:

  • 强引用
  • 弱参考
  • 无主参考文献

无主参考如何与弱参考不同?

什么时候使用无主参考安全?

无主引用是否存在安全风险,如C/C++中的悬空指针

Ile*_*ian 348

两者weakunowned引用都不strong会对引用的对象产生保持(也就是说它们不会增加保留计数以防止ARC释放引用的对象).

但为什么两个关键词?这种区别与Optional类型内置Swift语言的事实有关.关于它们的简短说明:可选类型提供了内存安全性(这与Swift的构造函数规则非常相似 - 为了提供这种优势,这些规则是严格的).

一个weak参考允许它的posibility成为nil(这个自动引用对象被释放情况),因此你的财产的类型必须是可选的-所以你,作为一个程序员,有责任在使用前要检查它(基本上是编译器强迫你尽可能地编写安全的代码.

一个unowned参考假定它永远不会成为nil它的生命周期中.必须在初始化期间设置无主引用 - 这意味着引用将被定义为非可选类型,可以安全地使用而无需检查.如果被引用的对象以某种方式被释放,那么当使用无主参考时,应用程序将崩溃.

来自Apple文档:

只要对该引用有效,就使用弱引用在其生命周期的某个时刻变为nil.相反,当您知道在初始化期间设置引用后永远不会为nil时,请使用无主引用.

在文档中有一些例子讨论了保留周期以及如何打破它们.所有这些示例都是从文档中提取.

weak关键字示例:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    weak var tenant: Person?
}
Run Code Online (Sandbox Code Playgroud)

现在,对于一些ASCII艺术(你应该去看看文档 - 他们有漂亮的图表):

Person ===(strong)==> Apartment
Person <==(weak)===== Apartment
Run Code Online (Sandbox Code Playgroud)

PersonApartment实施例显示的情况下两个属性,这两者都允许是零,有可能引起强烈的基准周期的潜力.使用弱引用可以最好地解决此方案.两个实体都可以存在,而不必严格依赖另一个实体.

unowned关键字示例:

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) { self.name = name }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer
    init(number: UInt64, customer: Customer) { self.number = number; self.customer = customer }
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,a Customer可能有也可能没有a CreditCard,但a CreditCard 总是与a相关联Customer.为了表示这一点,Customer该类具有可选card属性,但CreditCard该类具有非可选(和无主)customer属性.

Customer ===(strong)==> CreditCard
Customer <==(unowned)== CreditCard
Run Code Online (Sandbox Code Playgroud)

CustomerCreditCard实施例显示的情况下被允许是nil一个属性以及不能是nil必须引起强烈的基准周期的电势的另一属性.使用无主引用可以最好地解决此方案.

Apple的注意事项:

必须将弱引用声明为变量,以指示它们的值可以在运行时更改.弱引用不能声明为常量.

还有第三种情况,两个属性应始终具有值,并且一旦初始化完成,这两个属性都不应为nil.

还有一些经典的保留周期场景,以避免在使用闭包时.

为此,我鼓励您访问Apple文档,或阅读本书.

  • @JustinLevi,如果你声明两个属性都很弱,那么它们有可能被释放.该人士强烈提及公寓,因此公寓不会被取消分配.如果公寓对Person有相同的强引用,它们会创建一个保留周期 - 如果程序员知道它,可以在运行时打破它,但是否则只是内存泄漏.这是关于强,弱和无主的所有大惊小怪:更高层次的内存管理,因为ARC为我们做了所有肮脏的事情.避免保留周期是我们的工作. (4认同)
  • 这有点微不足道,但我发现公寓和人的例子有些混乱,这也提供了一个额外的解决方案来打破强大的参考周期.一个人的公寓是可选的,因此可以是零,公寓的租户是可选的,因此可以是零,因此两个属性都可以定义为弱.``` (3认同)
  • `weak var Person?`与`var Person?`之间有什么区别? (3认同)

Myx*_*tic 28

Q1."无主参考"与"弱参考"有何不同?

弱参考:

弱引用是一种引用,它不会强制保留它引用的实例,因此不会阻止ARC处理引用的实例.因为弱引用被允许具有"无值",所以必须将每个弱引用声明为具有可选类型.(Apple Docs)

无主参考:

与弱引用一样,无主引用并不会强烈保留它所引用的实例.然而,与弱引用不同,假定无主引用始终具有值.因此,无主引用始终定义为非可选类型.(Apple Docs)

何时使用每个:

只要对该引用有效,就使用弱引用在其生命周期的某个时刻变为nil.相反,当您知道在初始化期间设置引用后永远不会为nil时,请使用无主引用.(Apple Docs)


Q2.什么时候使用"无主参考"是安全的?

如上所述,假定无主参考始终具有值.因此,只有在确定引用永远不会为零时才应使用它.Apple Docs通过以下示例说明了无主引用的用例.

假设我们有两个类CustomerCreditCard.客户可以在没有信用卡的情况下存在,但是没有客户就不会存在信用卡,即可以假设信用卡将始终拥有客户.所以,他们应该有以下关系:

class Customer {
    var card: CreditCard?
}

class CreditCard {
    unowned let customer: Customer
}
Run Code Online (Sandbox Code Playgroud)

Q3."无主参考"是否引用了C/C++中的"悬空指针"等安全风险

我不这么认为.

由于无主引用只是保证具有值的弱引用,因此它不应该以任何方式存在安全风险.但是,如果您尝试在其引用的实例被取消分配后访问无主引用,则会触发运行时错误,应用程序将崩溃.

这是我看到的唯一风险.

链接到Apple Docs


Ten*_*Jay 26

如果封闭使用自我可能是零[弱自我].

如果自我永远不会在闭包中使用[无主自我].

如果你在使用[无主自我]时崩溃,那么在关闭的某个时刻self可能是零,你可能需要使用[弱自我].

查看关于在闭包中使用strong,weakunowned的示例:

https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html

  • 为什么不使用弱,即使自己永远不会是零,没有伤害对吗? (6认同)
  • 嗨@Boon - 这确实是一个关键问题. (3认同)

Abh*_*ngh 5

链接摘录

结论点很少

  • 要确定您是否甚至需要担心强,弱或无主,请问“我在处理引用类型”。如果您使用的是Structs或Enums,则ARC不会管理这些类型的内存,您甚至不必担心为这些常量或变量指定弱或无主。
  • 在父级引用子级的层次结构关系中,强引用是很好的选择,反之亦然。实际上,强引用是大多数时候最适合的引用类型。
  • 当两个实例相互关联时,请确保其中一个实例对另一个实例的引用较弱。
  • 当两个实例的关联方式使得其中一个实例在没有另一个实例的情况下不存在时,具有强制依赖关系的实例需要持有对另一个实例的无所有权引用。