var absences = [0, 2, 0, 4, 0, 3, 1, 0]
let midpoint = absences.count / 2
var firstHalf = absences.prefix(upTo: midpoint)
let secondHalf = absences.suffix(from: midpoint)
Apple的报价:
firstHalf和secondHalf切片都不会分配任何自己的新存储空间。相反,每个都提供了缺席数组存储的视图。
当我尝试变异firstHalf
如下:
firstHalf[1] = 19
firstHalf
的值发生了变化,但原始数组absences
保持不变(firstHalf[1]
等于19而absences[1]
等于2)
那么后台会发生什么。我是否通过改变数组切片来实例化一个新数组?
提前谢谢。
答案 0 :(得分:6)
是的,标准库的集合类型(包括Array
和ArraySlice
)都具有写时复制行为。这意味着他们可以共享元素与其他集合的存储,直到它们发生变异,在这种情况下,他们会自己复制它们。
在您的情况下,切片firstHalf
具有视图的基础数组缓冲区是非唯一引用的(因为absences
和secondHalf
都有一个视图) 。因此,当您进行变异firstHalf
时,会触发一个副本 - 创建一个包含切片元素的 new 缓冲区(但不一定是整个数组)。
firstHalf
现在可以使用absences
& secondHalf
都在旧数组缓冲区上共享视图。因此firstHalf
现在可以改变其缓冲区的元素而不影响原始数组的元素,从而保留了值语义。
答案 1 :(得分:4)
这是Swift集合在幕后使用的标准写时复制行为,在您尝试变异之前,它不会复制集合。有关写时复制的讨论,请参阅WWDC 2015视频Building Better Apps with Value Types in Swift。
评论in the code为我们澄清了这一点:
/// Slices Share Indices
/// --------------------
///
/// A collection and its slices share the same indices. An element of a
/// collection is located under the same index in a slice as in the base
/// collection, as long as neither the collection nor the slice has been
/// mutated since the slice was created.
...
/// Slices Inherit Collection Semantics
/// -----------------------------------
///
/// A slice inherits the value or reference semantics of its base collection.
/// That is, when working with a slice of a mutable
/// collection that has value semantics, such as an array, mutating the
/// original collection triggers a copy of that collection, and does not
/// affect the contents of the slice.