Swift的“内脏”:工具链,内部结构和中间表示
ARC:Swift如何管理内存
Swift使用一种称为自动引用计数(ARC)的内存管理技术。 ARC通过在创建对象实例时分配内存来存储对象实例来工作。 在此实例的分配内存中,可能有与其关联的任何属性值。 每当不再需要该实例时,ARC就会释放该内存以供Swift程序使用。 为了跟踪何时可以释放实例的内存,ARC会保留一个计数器,该计数器针对当前引用给其内存块的每个实例的任何属性,常量或变量。 此默认行为称为创建“强”引用。 让我们用一个简单的例子来演示一下。
首先,我们定义一个具有一个属性(名称)的Person
类。 此Person
类还具有一个init
和deinit
函数,该函数将在Person
实例被分配或释放时打印。
然后,我们可以将这两个实例链接在一起。
bob!.automobile =丰田
丰田!。驱动程序=鲍勃
现在,我们的强大参考资料如下所示。
我们现在有一个强大的参考周期。 即使bob
和toyota
都设置为nil
,它们之间仍然存在强引用。 bob
和toyota
对其各自实例的引用已消失,但是两个实例之间的引用意味着它们的内存不会在ARC下释放。
那么我们如何控制这种情况呢? Swift为我们提供了两个关键词, weak
引用和unowned
引用。
参考文献薄弱
弱引用是指不会对其引用的实例保持强大控制的引用,因此不会阻止ARC处置所引用的实例。 此行为可防止参考成为强大参考周期的一部分。 我们通过在属性或变量声明之前放置weak
关键字来指示弱引用。
即使存在对特定实例的弱引用,一旦删除了对该实例的最后一个强引用,该实例的内存也会被释放。 现在,我们可以通过将Automobile
的driver
属性设置为weak var
来用一个单词的修改来修改最后一个示例。
现在,如果我们进行与之前相同的分配,则将删除var bob
及其实例之间的引用,则bob
实例将在内存中重新分配,因为toyota
仅通过弱引用对其进行引用。
通常,定义弱引用的最佳方案是一个实例的生存期短于另一个实例。 在我们的示例中,汽车可以在没有驾驶员的情况下存在,因此我们在Automobile
内部对Person
对象设置了一个弱引用,因此我们没有以引用循环结尾。
无人参考
与弱引用类似, 无主引用也不会与其引用的实例保持紧密的链接。 但是,与弱引用不同,非拥有引用通常在另一个实例的寿命相似或更长时使用。
对于最后一个示例,假设我们有一个Customer
和一个RewardsAccount
对象。 在这种情况下,如果没有拥有该帐户的客户,奖励帐户就永远不会存在。 没有所有者的账户没有任何意义。 因此,我们在这里设置了RewardsAccount
对象,该对象具有对Customer
未拥有的引用。
现在,就像最近几次一样,如果我们创建一个客户实例和一个奖励帐户实例,则奖励帐户将仅包含对客户的未拥有的引用。
var mike:客户?
mike =客户(名称:“ Mike”)
mike!.card = RewardsAccount(帐户号码:“ 12345”,客户:mike!)
如果我们设置mike = nil
,现在将发生的是将删除对Customer
实例的强引用,并将释放该实例占用的内存。 结果,将不再有任何对RewardsAccount
实例的强引用,并且还将对其进行重新分配,以反映现实世界中预期的行为。
在许多情况下,您甚至不必担心实例之间的相互引用,但是如果您想最大程度地提高内存效率,Swift提供了一些非常简单的工具来实现。