关于Apple Substring
的文档,请说:
不要将子字符串存储的时间超过执行特定操作所需的时间。子字符串包含对它来自的字符串的整个存储的引用,而不仅仅是对它所呈现的部分的引用,即使没有对原始字符串的其他引用也是如此。因此,存储子字符串可以延长不再可访问的字符串数据的生命周期,这可能看起来是内存泄漏。
我感到困惑的是,String
是Swift中的值类型,它是如何导致内存泄漏的?
答案 0 :(得分:1)
Swift Arrays,Sets,Dictionaries和Strings具有值语义,但它们实际上是用于引用类型的copy-on-write包装器。换句话说,它们是struct
周围的所有class
包装器。这允许以下工作而无需复制:
let foo = "ABCDEFG"
let bar = foo
当您写入String
时,它使用标准库函数isUniquelyReferencedNonObjC
(除非它再次重命名)以检查是否有多个对支持对象的引用。如果是这样,它会在修改之前创建一个副本。
var foo = "ABCDEFG"
var bar = foo // no copy (yet)
bar += "HIJK" // backing object copied to keep foo and bar independent
当您使用Substring(或数组切片)时,您将获得对整个支持对象的引用,而不仅仅是您想要的位。这意味着如果你有一个非常大的字符串并且你有一个只有4个字符的子字符串,只要子字符串是活的,你就可以将整个字符串后备缓冲区保存在内存中。这是这个警告你的泄漏。
答案 1 :(得分:0)
鉴于Swift经常被描绘的方式,你的困惑是可以理解的。 String
,Array
和Dictionary
等类型显示值语义,但是是由值和引用类型的组合构造的库类型。
这些类型的实现使用动态分配的存储。此存储可以在不同值之间共享。但是,库工具用于实现 copy-on-write ,以便根据需要复制此类共享存储以维护值语义,即类似于值类型的行为。
HTH