斯威夫特有:

强引用 弱引用 无主的引用

无主引用与弱引用有何不同?

什么时候使用无主引用是安全的?

无主引用是否像C/ c++中的悬浮指针一样存在安全风险?


当前回答

link摘录

结论很少

To determine if you even need to worry about strong, weak, or unowned, ask, “Am I dealing with reference types”. If you’re working with Structs or Enums, ARC isn’t managing the memory for those Types and you don’t even need to worry about specifying weak or unowned for those constants or variables. Strong references are fine in hierarchical relationships where the parent references the child, but not vice-versa. In fact, strong references are the most appropraite kind of reference most of the time. When two instances are optionally related to one another, make sure that one of those instances holds a weak reference to the other. When two instances are related in such a way that one of the instances can’t exist without the other, the instance with the mandatory dependency needs to hold an unowned reference to the other instance.

其他回答

弱引用和无主引用都不会在被引用的对象上创建强持有(也就是说,它们不会增加保留计数以防止ARC释放被引用的对象)。

但为什么只有两个关键词呢?这种区别与可选类型是Swift语言内置的事实有关。长话短说:可选类型提供了内存安全(这与Swift的构造函数规则非常配合——为了提供这种好处,构造函数规则非常严格)。

弱引用允许它变成nil(当被引用的对象被释放时自动发生),因此你的属性类型必须是可选的——所以作为程序员,你有义务在使用它之前检查它(基本上编译器会强迫你尽可能多地编写安全代码)。

无主引用假定它在生命周期内永远不会变为nil。在初始化过程中必须设置无主引用——这意味着该引用将被定义为非可选类型,无需检查即可安全使用。如果被引用的对象以某种方式被释放,那么当使用无主引用时,应用程序将崩溃。

苹果文档中写道:

只要该引用成为有效,就使用弱引用 在生命周期的某个时刻为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?
}

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

Person ===(strong)==> Apartment
Person <==(weak)===== Apartment

Person和Apartment示例显示了一种情况,其中两个属性都被允许为nil,有可能导致强引用循环。这种情况最好使用弱引用来解决。两个实体可以不严格依赖于另一个实体而存在。

u主关键字示例:

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类有一个可选的card属性,而CreditCard类有一个非可选的(无主的)Customer属性。

Customer ===(strong)==> CreditCard
Customer <==(unowned)== CreditCard

Customer和CreditCard示例展示了这样一种情况:允许一个属性为nil,而另一个属性不能为nil,这可能会导致强引用循环。这种情况最好使用无主引用来解决。

苹果公司的说明:

弱引用必须声明为变量,以表明它们的 值可以在运行时更改。弱引用不能声明为 常数。

还有第三种情况,两个属性都应该有一个值,并且在初始化完成后,两个属性都不应该为nil。

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

为此,我鼓励你访问苹果文档,或阅读这本书。

如果self可以在闭包中为nil,请使用[weak self]。

如果self在闭包中永远不会为nil,请使用[无主的self]。

如果当你使用[un主self]时它崩溃了,那么self在闭包中的某个时候可能是nil,你可能需要使用[weak self]来代替。

查看在闭包中使用strong、weak和u主的示例:

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

无主引用是一种弱引用,用于两个对象之间存在同一生命周期关系的情况下,这时一个对象应该只属于另一个对象。它是一种在对象与其属性之一之间创建不可变绑定的方法。

In the example given in the intermediate swift WWDC video, a person owns a credit card, and a credit card can only have one holder. On the credit card, the person should not be an optional property, because you don't want to have a credit card floating around with only one owner. You could break this cycle by making the holder property on the credit a weak reference, but that also requires you to make it optional as well as variable (as opposed to constant). The unowned reference in this case means that although CreditCard does not have an owning stake in a Person, its life depends on it.

class Person {
    var card: CreditCard?
}

class CreditCard {

    unowned let holder: Person

    init (holder: Person) {
        self.holder = holder
    }
}

link摘录

结论很少

To determine if you even need to worry about strong, weak, or unowned, ask, “Am I dealing with reference types”. If you’re working with Structs or Enums, ARC isn’t managing the memory for those Types and you don’t even need to worry about specifying weak or unowned for those constants or variables. Strong references are fine in hierarchical relationships where the parent references the child, but not vice-versa. In fact, strong references are the most appropraite kind of reference most of the time. When two instances are optionally related to one another, make sure that one of those instances holds a weak reference to the other. When two instances are related in such a way that one of the instances can’t exist without the other, the instance with the mandatory dependency needs to hold an unowned reference to the other instance.

Both weak and unowned references will not impact the reference count of the object. But weak reference will always be optional i.e. it can be nil, whereas unowned references can never be nil so they will never be optional. When using an optional reference you will always have to handle the possibility of the object being nil. In case of an unowned reference you will have to ensure that the object is never nil. Using an unowned reference to a nil object will be similar to forcefully unwrapping an optional that is nil.

也就是说,在确定对象的生命周期大于引用的生命周期时,使用无主引用是安全的。如果不是这样,最好使用弱引用。

As for the third part of the question, I don’t think unowned reference is similar to a dangling pointer. When we talk about reference count, we usually refer to strong reference count of the object. Similarly swift maintains unowned reference count and weak reference counts for the object (weak reference points to something called a "side table" rather than the object itself ). When the strong reference count reaches zero, the object gets deinitialised, but it cannot be deallocated if the unowned reference count is more than zero.

悬空指针指向一个已经被释放的内存位置。但是在swift中,由于内存只有在对象有一个无主引用时才能被释放,所以它不会导致悬空指针。

有很多文章更详细地讨论了swift内存管理。这里有一个。