Swift的“内脏”:工具链,内部结构和中间表示

ARC:Swift如何管理内存

Swift使用一种称为自动引用计数(ARC)的内存管理技术。 ARC通过在创建对象实例时分配内存来存储对象实例来工作。 在此实例的分配内存中,可能有与其关联的任何属性值。 每当不再需要该实例时,ARC就会释放该内存以供Swift程序使用。 为了跟踪何时可以释放实例的内存,ARC会保留一个计数器,该计数器针对当前引用给其内存块的每个实例的任何属性,常量或变量。 此默认行为称为创建“强”引用。 让我们用一个简单的例子来演示一下。

首先,我们定义一个具有一个属性(名称)的Person类。 此Person类还具有一个initdeinit函数,该函数将在Person实例被分配或释放时打印。

然后,我们可以将这两个实例链接在一起。

  bob!.automobile =丰田 
丰田!。驱动程序=鲍勃

现在,我们的强大参考资料如下所示。

我们现在有一个强大的参考周期。 即使bobtoyota都设置为nil ,它们之间仍然存在强引用。 bobtoyota对其各自实例的引用已消失,但是两个实例之间的引用意味着它们的内存不会在ARC下释放。

那么我们如何控制这种情况呢? Swift为我们提供了两个关键词, weak引用和unowned引用。

参考文献薄弱

弱引用是指不会对其引用的实例保持强大控制的引用,因此不会阻止ARC处置所引用的实例。 此行为可防止参考成为强大参考周期的一部分。 我们通过在属性或变量声明之前放置weak关键字来指示弱引用。

即使存在对特定实例的弱引用,一旦删除了对该实例的最后一个强引用,该实例的内存也会被释放。 现在,我们可以通过将Automobiledriver属性设置为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提供了一些非常简单的工具来实现。