Value / Reference Type

當操作任何物件時就是在操作記憶體,到底是如何運作的呢?

三種記憶體區間

三大區塊

1. static memory:靜態變數(static),永遠存在的變數(ex. Swift中用特殊機制Lazy初始化)

2. stack memory:變數在方法結束會自動回收

3. heap memory:變數由使用者自己決定何時回收(ex. Swift中用ARC處理)

記憶體區塊的操作

Swift 裡的 Value Type 與 Reference Type

  • Value Type:Int, String, Array, Dict, Enum, Struct

    • 記錄在 stack memory

    • 因為變數在方法結束會自動回收

    • 所以賦值或是傳值都是"新的一份資料",即為 Pass By Value

  • Reference Type:Class, Closure

    • 記錄位址在stack memory,紀錄資料在heap memory

    • 因為變數在方法結束不會回收,是利用ARC回收

    • 所以賦值或是傳值都是"同一份資料",即為 Pass By Reference

  • Value Type 和 Reference Type 都只是基於操作記憶體的方式不同,而產生的簡稱

  • Value Type 和 Reference Type 萬年爭議哪個好?操作安全性?記憶體消耗?

var a = "0050"
var b = a
a = "2330"
print(b) // "0050"

// String 賦值是複製一份 String

func resetData(input: Int){
    input = "" // Error 無法編譯,input 預設是 let
}
struct Stock{
    var name: String = "0050"
}
var a = Stock()
var b = a
a.name = "2330"
print(b.name) // "0050"

// struct 賦值是複製一份 struct

func resetData(input: Stock){
    input.name = "" // Error 無法編譯,input 預設是 let
}
class Stock{
    var name: String = "0050"
}
var a = Stock()
var b = a
a.name = "2330"
print(b.name) // "2330"

// class 賦值是用同一份 class

func resetData(input: Stock){
    input.name = "Null"
}
resetData(input: a)
print(a.name)

// class 傳值是用同一份 class,可以在方法內修改

課後練習題(可以在playground上跑)

struct Car{
    var number = 0
    init(number: Int) {
        self.number = number
    }
}
var car0 = Car(number: 0)
var car1 = Car(number: 1)
var cars = [car0, car1]
var newCars = cars

cars.sort { $0.number > $1.number }
dump(cars) // [{number 1}, {number 0}]
dump(newCars) // [?, ?]

car0.number = 2
dump(cars) // [?, ?]
dump(newCars) // [?, ?]

cars[0].number = 3
dump(cars) // [?, ?]
dump(newCars) // [?, ?]
class Car{
    var number = 0
    init(number: Int) {
        self.number = number
    }
}
var car0 = Car(number: 0)
var car1 = Car(number: 1)
var cars = [car0, car1]
var newCars = cars

cars.sort { $0.number > $1.number }
dump(cars) // [{number 1}, {number 0}]
dump(newCars) // [?, ?]

car0.number = 2
dump(cars) // [?, ?]
dump(newCars) // [?, ?]

cars[0].number = 3
dump(cars) // [?, ?]
dump(newCars) // [?, ?]

Last updated

Was this helpful?