Swift Arrays,Sets,Dictionaries和Strings具有值语义,但它们实际上是用于引用类型的copy-on-write包装器。换句话说,他们都是 struct 周围的包装纸 class 。这允许以下工作而无需复制:
struct
class
let foo = "ABCDEFG" let bar = foo
当你写一个 String ,它使用标准库函数 isUniquelyReferencedNonObjC (除非它已被重命名)以检查是否有多个对支持对象的引用。如果是这样,它会在修改之前创建副本。
String
isUniquelyReferencedNonObjC
var foo = "ABCDEFG" var bar = foo // no copy (yet) bar += "HIJK" // backing object copied to keep foo and bar independent
当您使用Substring(或数组切片)时,您将获得对整个支持对象的引用,而不仅仅是您想要的位。这意味着如果你有一个非常大的字符串并且你只有4个字符的子字符串,只要子字符串是活动的,你就会将整个字符串后备缓冲区保存在内存中。这是这个警告你的泄漏。
鉴于Swift经常被描绘的方式,你的困惑是可以理解的。类型如 String , Array 和 Dictionary 目前价值 语义 但是是由值和引用类型的组合构造的库类型。
Array
Dictionary
这些类型的实现使用动态分配的存储。这个存储可以 共享 不同的价值之间。但是,库设施用于实现 写入时复制 以便根据需要复制此类共享存储以维护值语义,即类似于值类型的行为。
HTH