import UIKit
import Foundation
/swift 写时复制**/
func print(address o: UnsafeRawPointer ) {
print(String(format: “%p”, Int(bitPattern: o)))
}
var array1: [Int] = [0, 1, 2, 3]
var array2 = array1
print(address: array1) //0x600000078de0
print(address: array2) //0x600000078de0
array2.append(4)
print(address: array2)
/// 在 Swift 标准库中,像是 Array,Dictionary 和 Set 这样的集合类型是通过一种叫做写时复制 (copy-on-write) 的技术实现的
var x = [1,2,3]
var y = x
///如果我们创建了一个新的变量 y,并且把 x 赋值给它时,会发生复制,现在 x 和 y 含有的是独立的结构体:
/// 在内部,这些 Array 结构体含有指向某个内存的引用。这个内存就是数组中元素所存储的位置。 两个数组的引用指向的是内存中同一个位置,这两个数组共享了它们的存储部分。不过,当我们改变 x 的时候,这个共享会被检测到,内存将会被复制。这样一来,我们得以独立地改变两个 变量。昂贵的元素复制操作只在必要的时候发生,也就是我们改变这两个变量的时候发生复制:
x.append(5)
y.removeLast()
/// 这种行为就被称为写时复制。它的工作方式是,每当数组被改变,它首先检查它对存储缓冲区 的引用是否是唯一的,或者说,检查数组本身是不是这块缓冲区的唯一拥有者。如果是,那么缓冲区可以进行原地变更;也不会有复制被进行。不过,如果缓冲区有一个以上的持有者 (如本 例中),那么数组就需要先进行复制,然后对复制的值进行变化,而保持其他的持有者不受影响。
/**************************************************/
/// 类实现写时复制
/// 使用class,这是一个引用类型,因为当我们将引用类型分配给另一个时,两个变量将共享同一个实例,而不是像值类型一样复制它
final class Ref {
var value: T
init(value: T) {
self.value = value
}
}
/// 我们可以创建一个struct包装Ref:
struct Box {
private var ref: Ref
init(value: T) {
ref = Ref(value: value)
}
var value: T {
get { return ref.value }
set {
guard isKnownUniquelyReferenced(&ref) else {
ref = Ref(value: newValue)
return
}
ref.value = newValue
}
}
}
/// struct是一个值类型,当我们将它分配给另一个变量时,它的值被复制,而属性ref的实例仍由两个副本共享,因为它是一个引用类型
/// 为了提供高效的写时复制特性,我们需要知道一个对象是否是唯一的。如果它是唯一引用,那么我们就可以直接原地修改对象。否则,我们需要在修改前创 建对象的复制。在 Swift 中,我们可以使用 isKnownUniquelyReferenced 函数来检查某个引 用只有一个持有者。如果你将一个 Swift 类的实例传递给这个函数,并且没有其他变量强引用 这个对象的话,函数将返回 true。如果还有其他的强引用,则返回 false。不过,对于 Objective-C 的类,它会直接返回 false。
/// 我们想在一个使用struct类型的User中使用copy-on-write的:
struct User {
var identifier = 1
}
let user = User()
let box = Box(value: user)
var box2 = box // box2 shares instance of box.ref
box2.value.identifier = 2