2017.10.10更新
此乃官方博文的翻譯版本,短而精的文章,大家可以先看這個。下面是我自己的心得。
============================================================
- 如果變量(var)或者常量(let)的類型是基本類型(各種數值型、布爾、字符串、數組等),那么這個變量或者常量的是一個值。
如果變量或常量的類型是對象(也就是類),那么這個變量或者常量實際上是一個指針。
- 在swift為了簡化代碼,淡化了指針的定義,但為了和oc對接,底層應該還是存在指針的。
舉個例子:
class A {
var label1: UILabel = UILabel()
var a: [Int] = [0]
}
var a = A()
//指針
a.label1.text = "你好"
var label2 = a.label1
print(label2.text) //"你好"
label2.text = "不好"
print(label2.text) //"不好"
print(a.label1.text) //"不好"
//值
var b = a.a
print(b) //[0]
b = [1, 2]
print(b) //[1, 2]
print(a.a) //[0]
當把label2賦值給label1時,實際上是把label2的指針給了label1,當修改label2指向的數據時,label1指向的數據也同時被修改了。而把a賦值給b時,實際上是在內存中劃分出一個新的存儲空間b,把a的值復制到b中去,a和b的存儲空間互不干涉,所以無論怎么修改b的值a也不會受到影響。
2017.5.25更新,函數中的指針
同理:
- 函數的參數列表中的參數類型如果為基本類型,這個參數是一個值。
- 函數和參數列表中的參數類型如果是對象,這個參數實際上是一個指針。
舉個例子:
class A {
var number = 0
}
func change(_ a: A) {
a.number = 1
}
let a = A()
print(a.number) //0
change(a)
print(a.number) //1
舉個錯誤例子:
class A {
var number = 0
}
func change(_ a: A) {
let b = A()
a = b //這里會報錯
}
參數為指針時,指針(參數)指向的對象的屬性可以修改,但指針(參數)的值不能被修改。上例中b實際上就是一個與a不同的指針值。如果希望對參數值,參數類型要設為輸入輸出參數。
輸入輸出參數(In-Out Parameters)
前面說到函數的參數列表中的參數類型如果為基本類型,這個參數是一個值,且為常量。
如果你希望參數在函數中對參數作出修改并將結果保持到函數作用域外,可以在參數前加上inout
關鍵字。
例如:
func function(_ a: Int) {
a = 1
}
這種寫法會報錯。
func switchTwoInt(_ a: inout Int, _ b: inout Int) {
let c = a
a = b
b = a
}
var a = 0
var b = 1
print(a, b) //0,1
switchTwoInt(a, b)
print(a, b) //1,0
而這樣寫是正確的,且函數中對a,b兩個參數的修改保持到了函數體外。
swift3之前有還一種叫可變參數(Variable Parameter)的定義,3.0的時候去掉了,這里就不討論了。