是時候來看看對象和方法的生存空間了——想要了解面向對象,不知道方法和對象放在哪裡是一件很尷尬的事情——畢竟我們還是要面對垃圾收集器的,想要讓垃圾收集器幫你做更多的事情,我們就得一定程度上了解它的工作機制,了解方法和對象存放在哪裡,否則的話,你就又要寫出一個不堪一擊的程序來了!
我們在前邊的課程當中已經基本地提過堆的概念,沒錯,對象(實例)是放在堆上的——我將它形像地描述為“垃圾堆”。
被堆在棧中的方法
這個描述的標題看上去好像有點問題,但確實是形象的,方法都被放在棧當中,包括方法當中的局部變量。
這就是為什麼有時候局部變量又被稱作“棧變量”。
方法會被一個一個地壓入棧當中,先被調用的會被壓在最裡邊,最後被調用的則在棧頂,然後執行完畢的方法會從棧頂被彈出——我們來舉個栗子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class Weapon { func fire() {} } class Gun:Weapon { var ammo = 0 override func fire() { print("bang!") } func reload() {} func reloadAndFire() { self.fire() self.reload() self.fire() } } var gun = Gun() gun.reloadAndFire() |
還是熟悉的武器問題,當我們調用 reloadAndFire() 的時候,這個方法就被壓入棧頂——這個時候其實棧當中也就只有它一個,它調用了 fire () 方法,那麼 fire 被壓入棧頂,而 reloadAndFire() 由於還沒有執行完畢,就被壓到了下邊,然後 fire () 執行完畢了,就會被彈出棧頂, reloadAndFire() 又回到了原來的位置,那麼系統就會繼續執行它,然後就調用了 reload() 方法,然後又是 fire() ,最後 reloadAndFire() 執行完畢,也被彈出。
那在方法裡聲明的實例呢?
我們說過關於引用的內容,不論在任何地方創建實例,實例都是存在於堆上的,局部變量手裡握著的只能是遙控器。
實例裡的變量
說到實例,它裡邊的變量是跟著實例一起住在堆上的,他們的生存週期就要比局部變量長了很多——隨著實例生死。所以,我們在方法當中調用實例的變量,但方法被彈出實例變量也不會就此消失,而是等到實例被回收的時候才會跟著實例魂歸田雞。
創建一個對象
這個時候我們就能詳細的描述創建一個對象的全過程了:
- 聲明了儲存器,把它標記為某個實例的引用類型;
- 創建一個對象,它存在於堆
- 將堆上的對象與儲存器中的引用連接起來——給引用里傳入對象的地址。
本文由 落格博客 原創撰寫:落格博客 » “堆棧”:到底什麼事“堆”,什麼是“棧”?
轉載請保留出處和原文鏈接:https://www.logcg.com/archives/1133.html