[swift 進階]讀書筆記-第五章:結構體和類 C5P4_寫時複製

liaoWorking在掘金發表於2019-01-01

結構體和類

5.4寫時複製

定義:結構體的引用在改變的一瞬間是唯一的,不會有複製發生,記憶體的改變將在原地進行。

不太好理解的話我們一起看下面這個demo

    var x = [1,2,4]
    var y = x
    x.append(5) //1,2,4,5
    y.removeLast() //1,2
複製程式碼

這時,把x賦值給y時會發生複製。這時候兩個陣列的引用指向的是記憶體中的同一個位置。共享儲存部分。 當改變x時這個共享會被檢查到。 記憶體將會被複製出來。 我們就獨立的改變了兩個變數。 耗效能的元素複製操作只會在必要的時候傳送。這個就叫做寫時複製

####通俗來說: 複製時用的是一個記憶體地址,當某一個集合改變時恰到好處的複製了一份出來。

已經用官方非官方簡潔的語句解釋了三遍了朋友我相信你肯定懂的!

知識點: 複製結構體變數。裡面進行的淺複製。物件本身不會被複制。只有引用會被複制。

寫時複製的高效方法


1.首先要知道一個物件是否是唯一引用的,通過isKnownUniquelyReferenced(&obj)函式來獲取。
//會返回一個Bool值告訴你是否唯一 對於OC的物件直接返回false
isKnownUniquelyReferenced(&object: T)

    final class Box<A> {
        var unbox:A
        init(_ value:A) {
            self.unbox = value
        }
    }
    
    var a = Box(NSMutableData())
    isKnownUniquelyReferenced(&a)//true
    var b = a  
    isKnownUniquelyReferenced(&a)//false
    isKnownUniquelyReferenced(&b)//false
複製程式碼
2.然後判斷為false時執行寫是複製(這裡詳讀了一遍感覺比較艱深晦澀,大家可在參考下面的Demo理解)。
struct MyData {
    fileprivate var _data: Box<NSMutableData>
    var _dataForWriting: NSMutableData {
        mutating get {
            if !isKnownUniquelyReferenced(&_data) {//檢查對_data的引用是否是唯一性
                _data = Box(_data.unbox.mutableCopy() as! NSMutableData)
                print("Making a copy")
            }
            return _data.unbox
        }
    }
    init(_ data: NSData) {
        self._data = Box(data.mutableCopy() as! NSMutableData)
    }
}

extension MyData {
    mutating func append(_ other: MyData) {
        _dataForWriting.append(other._data.unbox as Data)
    }
}

let someBytes = MyData(NSData(base64Encoded: "wAEP/w==", options: [])!)
var empty = MyData(NSData())
var emptyCopy = empty
for _ in 0..<5 {
    empty.append(someBytes)

}
empty // <c0010fff c0010fff c0010fff c0010fff c0010fff>
emptyCopy // <>
複製程式碼

文章原始檔地址

相關文章