typealias Stuff = [[String]] // typically zillions of items
var stuff: [String: Stuff] = [:] // tens of these
当我深度复制† a
Stuff
,
spare: Stuff = original{
let line = $0.map{ $0 }
return line
}
在新手机上需要 1/2 秒,所以当然要避免。
现在说我正在与
Stuff
一起工作,就像这样 calculations(on: "Cats")
,严格从 stuff["Cats"]
阅读
///Strictly reading from Stuff
func calculations(on: String) {
guard stuff[on] != nil else { return }
.. = stuff[on]!.blah.blah
.. = stuff[on]!.blah.blah
..
.. dozens and dozens of reads from stuff[on]!
}
当然如果你的话会更整洁
///Strictly reading from Stuff
func calculations(on: String) {
guard let p = stuff[on] else { return }
.. = p.blah.blah
.. = p.blah.blah
..
.. dozens and dozens of reads from p
}
如果我这样做,
确实是不是深拷贝
stuff["Cats"]
吗?
那真的可靠吗,而且绝对不会这样做?
作为一个相关问题,我相信,但我不确定,
这将是您检查
p
是否确实不是 stuff["Cats"]
-> 的深层副本的方式
withUnsafePointer(to: &p[0][0]) {
print("p is at \($0)")
}
withUnsafePointer(to: &stuff["Cats"][0][0]) {
print("whereas stuff["Cats"][0][0] is at \($0)")
}
看起来不错吗?
† 顺便说一句,我真的不知道这是否是在 Swift 中深度复制 2D 字符串数组的最佳方法。
Array
具有写时复制行为:
与标准库中的所有可变大小集合一样,数组使用写时复制优化。阵列的多个副本共享相同的存储,直到您修改其中一个副本。
[...]
这意味着,如果一个数组与其他副本共享存储,则该数组上的第一个变异操作会产生复制该数组的成本。作为其存储的唯一所有者的数组可以就地执行变异操作。
虽然
let p = stuff[on]
将 stuff[on]
的值复制到 p
,但 Array
结构体的值很小 - 在我的机器上只有 8 个字节(参见 MemoryLayout<[[String]]>.size
)。
8 字节结构体值包含指向数组某个存储位置的指针,并且
p
和 stuff[on]
将指向相同的存储位置,如文档所述。
仅当您修改
stuff[on]
时,才会复制数组存储,例如添加另一个[String]
。 p
和 stuff[on]
现在将指向不同的存储位置。但即便如此,inner 数组仍将共享存储,因为您没有修改内部数组。