前言: 在Swift3中, 这些又发生了改变.
“Swift 中,许多基本类型,诸如String,Array和Dictionary类型均以结构体的形式实现。这意味着被赋值给新的常量或变量,或者被传入函数或方法中时,它们的值会被拷贝。”
在Swift3之前的情况:
Swift中数组(Array
)和字典(Dictionary
)类型均以结构体的形式实现.然而当数组被赋予一个常量或者变量, 或被传递给一个函数或方法时, 其拷贝行为与字典和其他结构体有些许不同.
字典类型的赋值和拷贝行为
无论何时将一个字典实例赋值给一个常量或变量, 或者传递给一个函数或方法, 这个字典都会在赋值或者调用发生时被拷贝.
如果字典实例中所存储的键和值是值类型(结构体或枚举), 当赋值或调用发生时, 都会被拷贝, 是值拷贝, 相反, 如果键和值是引用类型, 被拷贝的将会是引用, 而不是被它们引用的类实例或函数.
var ages = ["Peter": 23, "Wei": 35, "Anish": 65, "Katya": 19]
var copiedAges = ages
修改:
copiedAges["Peter"] = 24
print(ages["Peter"])
// 输出 "23"
是值拷贝
数组的赋值和拷贝行为
在Swift中, 数组类型的赋值和拷贝行为要比字典复杂很多. 当操作数组内容时, 数组能提供接近C语言的性能, 并且拷贝行为只有在必要时才会发生.
如果你将一个数组实例赋值给一个变量或常量, 或者将其作为参数传递给函数或方法调用, 在事件发生时数组的内容不会被拷贝. 相反, 数组公用相同的元素序列. 当你在一个数组内修改某一个元素, 修改结果也会在另一数组显示.
对数组来说 拷贝行为仅仅当操作有可能修改数组长度时才会发生. 这种行为包括了appending
. inserting
. removing
或者使用范围下边去替换这一范围内的元素. 只有当数组拷贝确定要发生时, 数组内容的行为规则与字典中键值得相同.
var a=[1,2,3]
var b=a
var c=a
使用下标语法以得到数组的第一个元素
print(a[0])
// 1
print(b[0])
// 1
print(c[0])
// 1
如果通过下标语法修改数组中某一元素的值, 那么a,b,c中的对应值都会发生改变.当用下标语法修改某一值时, 并没有拷贝行为伴随发生, 因为下标语法修改值时没有改变数组长度:
a[0] = 42
print(a[0])
// 42
print(b[0])
// 42
println(c[0])
// 42
Swift 管理所有的值拷贝以确保性能最优化的性能,所以你也没有必要去避免赋值以保证最优性能。(实际赋值由系统管理优化)
然而当你给a附加新元素时, 数组的长度会改变, 当附加元素这一事件发生时, Swift会创建这个数组的一个拷贝, 从此以后, a将会是原数组的一个独立拷贝. 从此以后, a将会是原数组的一个独立拷贝. 拷贝发生后, 如果再修改a中元素值得话, a将会返回与b,c不同的结果,因为后者引用的是原来的数组.
a.append(4)
a[0] = 777
print(a[0])
// 777
print(b[0])
// 42
print(c[0])
// 42