Value Type相比Reference Type,最大的優勢在於記憶體使用的效率。Value Type是在Stack上操作,Reference Type則在Heap中。Stack上的操作僅僅是單個指標的上下移動,而Heap則牽涉到合併、移位、重新連結等。也就是說Swift這樣設計,大幅減少了Heap上的記憶體分配和回收次數,同時又將值傳遞和複製的開銷降到最低。
為了對兩者在記憶體中的表現有更深的印象,稍微複習一下Stack與Heap:
- Value Type與Reference Type的 “變數” 都會存放在Stack,但後者的值會放在Heap。
- Stack為靜態記憶體配置、Heap則為動態記憶體配置
- Stack為固定Size,超過會造成 => Stack-overflow
- Heap的資源要注意Memory Leak
- Stack為向下、往低位址,Heap為向上、往高位址
- Memory中的Heap,與資料結構中的Heap沒有任何關係,只是名字剛好一樣
- Memory中的Stack,遵循資料結構中的Stack處理流程
由於Stack在操作上相對簡單,加上程式的編寫也跟Stack push pop 的邏輯相近,因此區域變數(return & release)與可預測的資源會被分配到Stack,並依照LIFO的方式處理 -> 靜態記憶體配置
Heap則會存放物件或不可預測的資源 -> 動態記憶體配置
Stack & Heap 範例
func hello() {
var b = "hello"
// hello() stackFrame = [b], heap = {}
var c = "Hi".
// hello() stackFrame = [b, c], heap = {}
var obj = Earth()
// hello() stackFrame = [b, c, ref -> obj], heap = { {Object obj} }
return // {Object obj} in heap should be released by ARC
} // hello() stackFrame = [], heap = {}
func test() {
var test = "123" // test() stackFrame = [test], heap = {}
return
} // test() stackFrame = [], heap = {}
func main() {
// sub [] in stack is stackFrame of main()
// stack = [[]], heap = {}
var a = 1
// stack = [[a]], heap = {}
hello() // stack = [[a, hello() stackFrame]], heap = {}
// stack = [[a]], heap = {}
test() // stack = [[a, test() stackFrame]], heap = {}
// stack = [[a]], heap = {}
}
// stack = [], heap = {}