Swift中的值和指標

weixin_33724059發表於2016-10-18

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的時候去掉了,這裡就不討論了。

相關文章