Swift5 写入时复制 copy-on-write

swift的数组是值类型,值类型的一个特点是在传递和赋值时进行复制。swift使用了copy-on-write来避免频繁复制带来的额外开销。只有当多个对象指向相同的资源,其中一个对象尝试修改资源内容时,copy才会触发。

维基百科描述很清晰

写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者(callers)同时请求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的(transparently)。此作法主要的优点是如果调用者没有修改该资源,就不会有副本(private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源。

苹果关于数组使用copy-on-write的文档

Arrays, like all variable-size collections in the standard library, use copy-on-write optimization. Multiple copies of an array share the same storage until you modify one of the copies. When that happens, the array being modified replaces its storage with a uniquely owned copy of itself, which is then modified in place. Optimizations are sometimes applied that can reduce the amount of copying.
This means that if an array is sharing storage with other copies, the first mutating operation on that array incurs the cost of copying the array. An array that is the sole owner of its storage can perform mutating operations in place.

简单概述和演示:

// 打印对象的地址
func printPoint(name:String,point:UnsafePointer){
    print("\(name):\(point)")
}

var numberArray1 = [1, 2, 3, 4, 5]
var numberArray2 = numberArray1

printPoint(name: "numberArray1", point: numberArray1)
printPoint(name: "numberArray2", point: numberArray2)

numberArray2.append(6)

printPoint(name: "numberArray1", point: numberArray1)
printPoint(name: "numberArray2", point: numberArray2)

打印结果:
numberArray1:0x0000600000eb5560
numberArray2:0x0000600000eb5560
numberArray1:0x0000600000eb5560
numberArray2:0x00006000006b5750

可以看到,原本numberArray1numberArray2指向同一地址,当numberArray2要添加6时,触发了copy操作,把源地址0x0000600000eb5560的内容copy了一份到新地址0x00006000006b5750,然后在新地址上添加新元素6,赋值给numberArray2
最终numberArray1指向的地址没有改变,numberArray2指向新的地址

最后

虽然数组是值类型,但我们的赋值操作不会产生性能耗损,因为复制发生在有条件的内容改变时,而不是赋值的时候

你可能感兴趣的:(Swift5 写入时复制 copy-on-write)