在Swift結構體中如何?寫時複製?

來源:互聯網
上載者:User

標籤:

結構體(Struct)在Swift語言中佔有重要地位,在Swift標準庫中,大約有90%的公開類型都是結構體,包括我們常用的Array、String、Dictionary。結構體相比類,一個最重要的特性就是它是實值型別,而類似參考型別。實值型別是通過複製值來賦值的,而不是引用同一個記憶體位址,這樣就不存在資料共用的問題,能防止意外的資料改變,並且它是安全執行緒的。

舉一個很簡單的例子,在objc中,數組是類,是參考型別,在Swift中,數組是結構體,是實值型別。因此下面的代碼中:

let array1 = NSMutableArray(array: ["lihua", "liming"])

let array2 = array1

array1.addObject("xiaowang")

array2

array1 和 array2 最後都變成了 ["lihua", "liming", "xiaowang"] ,也就是 array1 的改變會導致 array2 也發生改變,因為它們兩個都是參考型別,並且都引用了同一個記憶體位址。

而在Swift中,就不存在這樣的問題:

var array3 = ["lihua", "liming"]

var array4 = array3

array3.append("xiaowang")

array4

這段代碼執行後, array3 變成了 ["lihua", "liming", "xiaowang"] ,而 array4 還是 ["lihua", "liming"] 。這就是結構體和類的最大區別。

那麼,是不是每次將struct賦值給其它變數或者傳遞給函數時都會發生複製呢。答案是否定的,在Swift中的Array、Dictionary、String這些類型中,儘管它們都是實值型別,但在Swift的具體實現中做了最佳化,可以避免不必要的複製。在《The Swift Programming Language (Swift 2.2)》一書的“Classes and Structures”一章末尾寫道:

The description above refers to the “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization.

在Swift中採用的最佳化方式叫做寫時複製技術,簡單的說就是,只有當一個結構體發生了寫入行為時才會有複製行為。具體的做法就是,在結構體內部用一個參考型別來儲存實際的資料,在不進行寫入操作的普通傳遞過程中,都是將內部的reference的應用計數+1,在進行寫入操作時,對內部的reference做一次copy操作用來儲存新的資料,防止和之前的reference產生意外的資料共用。

在Swift中有一個方法: isUniquelyReferencedNonObjC (Swift 2.2),在Swift3中這個函數變成了這樣:isKnownUniquelyReferenced ,他能檢查一個類的執行個體是不是唯一的引用,如果是,我們就不需要對結構體執行個體進行複製,如果不是,說明對象被不同的結構體共用,這時對它變更就需要進行複製。

但這個函數只對Swift對象有用,如果要用在Objective-C對象上,可以將OC對象用Swift進行一次封裝。

下面是《Advanced Swift》書中的一個實現寫時複製技術的代碼執行個體,我已經把它轉為Swift3了:

final class Box {

var unbox: A

init(_ value: A) {

unbox = value

}

}

struct GaussianBlur {

private var boxedFilter: Box= {

var filter = CIFilter(name: "CIGaussianBlur", withInputParameters: [:])!

filter.setDefaults()

return Box(filter)

}()

fileprivate var filter: CIFilter {

get { return boxedFilter.unbox }

set { boxedFilter = Box(newValue) }

}

private var filterForWriting: CIFilter {

mutating get {

if !isKnownUniquelyReferenced(&boxedFilter) {

filter = filter.copy() as! CIFilter

}

return filter

}

}

var inputImage: CIImage {

get { return filter.value(forKey: kCIInputImageKey) as! CIImage }

set { filterForWriting.setValue(newValue, forKey: kCIInputImageKey) }

}

var radius: Double {

get { return filter.value(forKey: kCIInputRadiusKey) as! Double }

set { filterForWriting.setValue(newValue, forKey: kCIInputRadiusKey) }

}

}

extension GaussianBlur {

var outputImage: CIImage? {

return filter.outputImage

}

}

文章來源:小悟空

在Swift結構體中如何?寫時複製?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.