改变 ArraySlice 会实例化一个新的数组实例吗?
Would mutating an ArraySlice instantiate a new array instance?
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 的引述:
Neither the firstHalf nor secondHalf slices allocate any new storage of their own. Instead, each presents a view onto the storage of the absences array.
当我尝试按如下方式改变 firstHalf
时:
firstHalf[1] = 19
firstHalf
的值发生变化,但原始数组 absences
保持不变(firstHalf[1]
等于 19 而 absences[1]
等于 2)
那么在后台发生了什么。我是否通过改变数组切片来实例化一个新数组?
提前致谢。
是的,标准库的集合类型,包括 Array
和 ArraySlice
,都具有写时复制行为。这意味着它们可以 与其他集合共享 存储它们的元素,直到它们发生变异,在这种情况下,它们将获取它们自己的副本。
在您的情况下,切片 firstHalf
对其具有视图的底层数组缓冲区是非唯一引用的(因为 absences
和 secondHalf
也对其具有视图).因此,当你去改变 firstHalf
时,一个副本被触发——创建一个包含切片元素的 new 缓冲区(但不一定是 entire数组)。
firstHalf
现在对这个新缓冲区有独特的看法,absences
和 secondHalf
都共享对旧数组缓冲区的看法。因此 firstHalf
现在可以在不影响原始数组元素的情况下改变其缓冲区的元素,从而保留值语义。
这是 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.
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 的引述:
Neither the firstHalf nor secondHalf slices allocate any new storage of their own. Instead, each presents a view onto the storage of the absences array.
当我尝试按如下方式改变 firstHalf
时:
firstHalf[1] = 19
firstHalf
的值发生变化,但原始数组 absences
保持不变(firstHalf[1]
等于 19 而 absences[1]
等于 2)
那么在后台发生了什么。我是否通过改变数组切片来实例化一个新数组?
提前致谢。
是的,标准库的集合类型,包括 Array
和 ArraySlice
,都具有写时复制行为。这意味着它们可以 与其他集合共享 存储它们的元素,直到它们发生变异,在这种情况下,它们将获取它们自己的副本。
在您的情况下,切片 firstHalf
对其具有视图的底层数组缓冲区是非唯一引用的(因为 absences
和 secondHalf
也对其具有视图).因此,当你去改变 firstHalf
时,一个副本被触发——创建一个包含切片元素的 new 缓冲区(但不一定是 entire数组)。
firstHalf
现在对这个新缓冲区有独特的看法,absences
和 secondHalf
都共享对旧数组缓冲区的看法。因此 firstHalf
现在可以在不影响原始数组元素的情况下改变其缓冲区的元素,从而保留值语义。
这是 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.