Copy-on-Write技術(shù)
Swift針對(duì)標(biāo)準(zhǔn)庫(kù)中的集合類(lèi)型(Array辽话、Dictionary、Set)進(jìn)行優(yōu)化。當(dāng)變量指向的內(nèi)存空間并沒(méi)有發(fā)生改變辱志,進(jìn)行拷貝時(shí)虐急,只會(huì)進(jìn)行淺拷貝箱残。只有當(dāng)值發(fā)生改變時(shí)才會(huì)進(jìn)行深拷貝。
/**
* 讀取變量指向地址
*/
func address(of object: UnsafeRawPointer) -> String {
let addr = Int(bitPattern: object)
return String(format: "%p", addr)
}
var array1 = [1, 2, 3, 4, 5, 6]
var array2 = array1
print(address(of: &array1))
print(address(of: &array2))
// 結(jié)果:
// 0x100527f60
// 0x100527f60
array1和array2都是指向地址是同一個(gè)空間,所以可以看出當(dāng)前是淺拷貝
func address(of object: UnsafeRawPointer) -> String {
let addr = Int(bitPattern: object)
return String(format: "%p", addr)
}
var array1 = [1, 2, 3, 4, 5, 6]
var array2 = array1
array2[0] = 2 // 值發(fā)生了改變
print(address(of: &array1))
print(address(of: &array2))
// 結(jié)果:
// 0x100593ec0
// 0x102800230
array1和array2指向了不同的空間被辑,所以可以看出當(dāng)前是淺拷貝
Copy-on-Write技術(shù)的實(shí)現(xiàn)
用set來(lái)進(jìn)行講解
final class Ref<T> {
var val: T
init(_ v: T) {val = v}
}
struct Box<T> {
var ref: Ref<T>
init(_ x: T) {ref = Ref(x)}
var value: T {
get { return ref.val } // 讀取操作
set { // 修改操作
if (!isUniquelyReferencedNonObjC(&ref)) { // 判斷當(dāng)前的類(lèi)型值是否唯一的引用(即引用計(jì)算器為1)
ref = Ref(newValue) // 如果不是唯一的引用燎悍,則生成一個(gè)新的類(lèi)型值并返回
return
}
ref.val = newValue // 如果是唯一的引用,則直接用當(dāng)前的類(lèi)型值進(jìn)行修改
}
}
}
Array盼理、Dictinary谈山、Set每次進(jìn)行修改前,都會(huì)通過(guò)類(lèi)似isUniquelyReferencedNonObjC進(jìn)行判斷宏怔,判斷是否是唯一的引用(即引用計(jì)數(shù)器為1)奏路。若不為1,則創(chuàng)建新的類(lèi)型值并返回臊诊。若是唯一的則直接賦值鸽粉。
注意點(diǎn)
當(dāng)Array、Dictionary抓艳、Set并沒(méi)有進(jìn)行修改操作值潜叛,建議把變量設(shè)置為let
參考:
https://swift.gg/2018/12/06/friday-qa-2015-04-17-lets-build-swiftarray/
https://juejin.im/post/5cbd31225188250a6e7e5d35