Would mutating an ArraySlice instantiate a new array instance?

邮差的信 提交于 2019-12-18 08:24:51

问题


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)

Quotation from 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.

When I try to mutate firstHalf as the following:

firstHalf[1] = 19

the values of firstHalf changes but the original array absences remains the same (firstHalf[1] is equal to 19 while absences[1] equals to 2) So what happens in the background. Did I instantiate a new array by mutating the array slice? Thanks in advance.


回答1:


Yes, the standard library's collection types, including Array and ArraySlice, all have copy-on-write behaviour. This means that they can share storage of their elements with other collections until they are mutated, in which case they will take their own copy of them.

In your case, the underlying array buffer that the slice firstHalf has a view onto is non-uniquely referenced (as both absences & secondHalf also have a view onto it). Therefore when you go to mutate firstHalf, a copy is triggered – creating a new buffer containing the elements of the slice (but not necessarily the entire array).

firstHalf now has a unique view onto this new buffer, with absences & secondHalf both sharing a view onto the old array buffer. Therefore firstHalf can now mutate the elements of its buffer without affecting the elements of the original array, thus preserving value semantics.




回答2:


This is the standard copy-on-write behavior employed behind the scenes by Swift collections, where it doesn't copy the collection until you attempt to mutate it. For discussion of copy-on-write, see WWDC 2015 video Building Better Apps with Value Types in Swift.

The comments in the code clarify this for us:

/// 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.


来源:https://stackoverflow.com/questions/43589637/would-mutating-an-arrayslice-instantiate-a-new-array-instance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!