前言: 在Swift3中, 這些又發(fā)生了改變.
“Swift 中,許多基本類型,諸如String,Array和Dictionary類型均以結(jié)構(gòu)體的形式實現(xiàn)。這意味著被賦值給新的常量或變量,或者被傳入函數(shù)或方法中時,它們的值會被拷貝。”
在Swift3之前的情況:
Swift中數(shù)組(Array
)和字典(Dictionary
)類型均以結(jié)構(gòu)體的形式實現(xiàn).然而當數(shù)組被賦予一個常量或者變量, 或被傳遞給一個函數(shù)或方法時, 其拷貝行為與字典和其他結(jié)構(gòu)體有些許不同.
字典類型的賦值和拷貝行為
無論何時將一個字典實例賦值給一個常量或變量, 或者傳遞給一個函數(shù)或方法, 這個字典都會在賦值或者調(diào)用發(fā)生時被拷貝.
如果字典實例中所存儲的鍵和值是值類型(結(jié)構(gòu)體或枚舉), 當賦值或調(diào)用發(fā)生時, 都會被拷貝, 是值拷貝, 相反, 如果鍵和值是引用類型, 被拷貝的將會是引用, 而不是被它們引用的類實例或函數(shù).
var ages = ["Peter": 23, "Wei": 35, "Anish": 65, "Katya": 19]
var copiedAges = ages
修改:
copiedAges["Peter"] = 24
print(ages["Peter"])
// 輸出 "23"
是值拷貝
數(shù)組的賦值和拷貝行為
在Swift中, 數(shù)組類型的賦值和拷貝行為要比字典復(fù)雜很多. 當操作數(shù)組內(nèi)容時, 數(shù)組能提供接近C語言的性能, 并且拷貝行為只有在必要時才會發(fā)生.
如果你將一個數(shù)組實例賦值給一個變量或常量, 或者將其作為參數(shù)傳遞給函數(shù)或方法調(diào)用, 在事件發(fā)生時數(shù)組的內(nèi)容不會被拷貝. 相反, 數(shù)組公用相同的元素序列. 當你在一個數(shù)組內(nèi)修改某一個元素, 修改結(jié)果也會在另一數(shù)組顯示.
對數(shù)組來說 拷貝行為僅僅當操作有可能修改數(shù)組長度時才會發(fā)生. 這種行為包括了appending
. inserting
. removing
或者使用范圍下邊去替換這一范圍內(nèi)的元素. 只有當數(shù)組拷貝確定要發(fā)生時, 數(shù)組內(nèi)容的行為規(guī)則與字典中鍵值得相同.
var a=[1,2,3]
var b=a
var c=a
使用下標語法以得到數(shù)組的第一個元素
print(a[0])
// 1
print(b[0])
// 1
print(c[0])
// 1
如果通過下標語法修改數(shù)組中某一元素的值, 那么a,b,c中的對應(yīng)值都會發(fā)生改變.當用下標語法修改某一值時, 并沒有拷貝行為伴隨發(fā)生, 因為下標語法修改值時沒有改變數(shù)組長度:
a[0] = 42
print(a[0])
// 42
print(b[0])
// 42
println(c[0])
// 42
Swift 管理所有的值拷貝以確保性能最優(yōu)化的性能,所以你也沒有必要去避免賦值以保證最優(yōu)性能。(實際賦值由系統(tǒng)管理優(yōu)化)
然而當你給a附加新元素時, 數(shù)組的長度會改變, 當附加元素這一事件發(fā)生時, Swift會創(chuàng)建這個數(shù)組的一個拷貝, 從此以后, a將會是原數(shù)組的一個獨立拷貝. 從此以后, a將會是原數(shù)組的一個獨立拷貝. 拷貝發(fā)生后, 如果再修改a中元素值得話, a將會返回與b,c不同的結(jié)果,因為后者引用的是原來的數(shù)組.
a.append(4)
a[0] = 777
print(a[0])
// 777
print(b[0])
// 42
print(c[0])
// 42