弱引用和无主引用之间有什么区别?
Swift有:
- 强烈的参考
- 弱引用
- 无主的参考
一个无主的参考与一个弱参考有什么不同?
何时可以安全地使用无主引用?
在C / C ++中,无主引用是否存在像悬挂指针这样的安全风险?
weak
引用和unowned
引用都不会在引用的对象上产生strong
保留(也就是说,它们不会增加保留计数,以防止ARC将引用的对象释放)。
但为什么两个关键字? 这种区别与Optional
types内置Swift语言的事实有关。 长话短说: 可选types提供了内存安全(这与Swift的构造函数规则非常协调 – 为了提供这个好处,它是严格的)。
一个weak
引用允许它的可能性成为nil
(当被引用的对象被释放时这会自动发生),因此你的属性的types必须是可选的 – 所以作为程序员,你必须在使用它之前检查它(基本上编译器强制你写尽可能多的代码)。
一个unowned
参考文献假设,在它的一生中它永远不会变成nil
。 必须在初始化期间设置无主引用 – 这意味着引用将被定义为非可选types,可以安全地使用而不用检查。 如果被引用的对象以某种方式被解除分配,那么当使用无主引用时,该应用程序将崩溃。
从苹果文档 :
使用一个弱引用,只要该引用在其有效期内在某个时间点成为零。 相反,如果您知道在初始化过程中设置的引用永远不会为零,请使用无主引用。
在文档中有一些例子讨论了保留周期以及如何打破它们。 所有这些例子都是从文档中提取的 。
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? }
而现在,对于一些ASCII艺术(你应该去看看文档 – 他们有漂亮的图表):
Person ===(strong)==> Apartment Person <==(weak)===== Apartment
Person
和Apartment
例子显示了两个属性都允许为零的情况有可能导致强烈的参考周期的情况。 这种情况最好用弱引用解决。 两个实体都可以存在,而不会严格依赖另一个实体。
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 } }
在这个例子中, Customer
可能有也可能没有CreditCard
,但CreditCard
将始终与Customer
相关联。 为了表示这一点, Customer
类有一个可选的card
属性,但是CreditCard
类有一个非可选的(和无主的) customer
属性。
Customer ===(strong)==> CreditCard Customer <==(unowned)== CreditCard
Customer
和CreditCard
示例显示了一种情况,一个属性允许为零,另一个属性不能为零有可能导致强烈的引用循环。 这种情况最好用无主的参考来解决。
苹果的注意事项:
弱引用必须声明为variables,以表明它们的值可以在运行时改变。 弱引用不能被声明为常量。
还有第三种情况,当两个属性都应该有一个值,并且一旦初始化完成,这两个属性都不应该为零。
而且还有经典的保留周期情景,以避免在使用闭包时。
为此,我鼓励您访问Apple文档 ,或者阅读本书 。
Q1。 “无主参考”与“弱参考”有什么不同?
弱参考:
一个弱引用是一个引用,它并不能保持它所引用的实例的强壮,所以不会停止引用实例的ARC。 因为弱引用被允许有“没有价值”,所以你必须声明每一个弱引用具有可选types。 (Apple Docs)
无主的参考:
就像弱引用一样,一个无主引用并不能保持它引用的实例。 然而,与弱引用不同的是,一个无主引用被认为总是有一个值。 正因为如此,一个无主的引用总是被定义为一个非可选的types。 (Apple Docs)
何时使用每个:
使用一个弱引用,只要该引用在其有效期内在某个时间点成为零。 相反,如果您知道在初始化过程中设置的引用永远不会为零,请使用无主引用。 (Apple Docs)
Q2。 什么时候使用“无主参考”是安全的?
如上所述,一个无主的引用被认为总是有一个值。 所以你应该只在确定引用不会为零时才使用它。 Apple Docs通过以下示例说明了无主引用的用例。
假设我们有两个类Customer
和CreditCard
。 客户可以不用信用卡而存在,但是没有客户就不会存在信用卡,也就是说可以假定信用卡总是有客户。 所以他们应该有以下关系:
class Customer { var card: CreditCard? } class CreditCard { unowned let customer: Customer }
Q3。 “无主的引用”在C / C ++中引用像“悬挂指针”这样的安全风险
我不这么认为。
由于无主的引用只是保证具有价值的弱引用,所以不应以任何方式存在安全风险。 但是,如果尝试在其引用的实例解除分配后访问无主引用,则会触发运行时错误,并且应用程序将崩溃。
这是我看到的唯一的风险。
链接到Apple Docs
如果自我可能在封闭使用[弱自我] 。
如果封闭使用[无主的自我], 自我永远不会成为零。
如果使用[unowned self]时崩溃了,那么self可能在这个闭包的某一点上是零,而你可能需要使用[weak self] 。
查看关于使用强 , 弱和无主闭包的例子:
链接提取
几点总结
- 要确定你是否需要担心强,弱或者无主,请问“我在处理参考types”。 如果您正在使用Structs或Enums,则ARC不会pipe理这些types的内存,您甚至不必担心为这些常量或variables指定弱或无主。
- 强引用在父级引用子级的层次关系中很好,但反之亦然。 事实上,强大的参考是大多数时候最合适的参考。
- 当两个实例可选地相互关联时,确保其中一个实例对另一个实例具有弱引用。
- 当两个实例相关联时,如果其中一个实例不能在没有另一个实例的情况下存在,那么具有强制性依赖关系的实例需要对另一个实例持有一个无主引用。
无主引用是一种弱引用,在两个对象之间的相同生命周期关系的情况下,对象只能由另一个对象拥有。 这是一种在对象和其中一个属性之间创build不可变绑定的方法。
在中级快速WWDCvideo中给出的例子中,一个人拥有一张信用卡,一张信用卡只能拥有一个持卡人。 在信用卡上,这个人不应该是一个可选的财产,因为你不想只有一个所有者的信用卡。 你可以通过使信用证持有人属性成为一个弱引用来打破这个循环,但这也要求你把它变成可选的(而不是常数)。 在这种情况下,无所谓的提法意味着,尽pipeCreditCard在一个人身上没有所有权,但它的生命依赖于它。
class Person { var card: CreditCard? } class CreditCard { unowned let holder: Person init (holder: Person) { self.holder = holder } }