感覺上一周給自己挖了一個深坑遣臼,在繁重的工作任務之下硼一,感覺自己完全沒有辦法重現(xiàn)當時聯(lián)系過的js的棧與隊列,再深刻剖析一下數(shù)據(jù)結(jié)構中的棧與隊列的形式與變化。
不管怎樣季希,先解決一個小坑项栏,今天看了看計算機的堆棧女蜈,當然堆棧還是與內(nèi)存有關的澜共,那究竟計算機中的堆棧是什么呢?
首先样勃,說堆椃涂保肯定要從內(nèi)存開始討論。計算機五個部分彤灶,輸入設備看幼,輸出設備,運算器幌陕,存儲器诵姜,控制器,內(nèi)存自然是屬于存儲器的搏熄。存儲器包括很多棚唆,包括硬盤,包括內(nèi)存心例,包括虛存宵凌。當然廣義上來說,u盤等存儲也是存儲器止后,不過這都是我們平常了解的概念瞎惫,計算機的存儲器其體系大概是這樣的:
如圖所示溜腐,上文所說的硬盤,內(nèi)存瓜喇,實際上都包含在主存之中挺益,而所說的U盤其實就屬于輔存部分。此外我剛才還說到了虛存乘寒,上圖之中也體現(xiàn)了緩存望众,這其實又可以畫出一個層次圖。
實際上對于電腦的物理設備就是伞辛,CPU,內(nèi)存烂翰,硬盤(二級存儲),而緩存蚤氏,虛存是為了計算機更好的處理數(shù)據(jù)而虛擬出來的區(qū)塊甘耿。緩存是在內(nèi)存之上的一塊空間,不過相比其他的內(nèi)存區(qū)域瞧捌,他的存取速度要快很多棵里;虛擬內(nèi)存是處于二級存儲上的一塊空間润文,它是用來存儲內(nèi)存上不常用的一些符號和數(shù)據(jù)等內(nèi)容姐呐,相比于普通二級存儲它自然也速度也會快一些。其邏輯自然如上圖典蝌,CPU需要數(shù)據(jù)的時候會先從緩存中尋找曙砂,如果尋找不到,再到內(nèi)存中尋找骏掀,如果還是沒有鸠澈,會再到虛擬內(nèi)存中尋找,最后找不到會從二級存儲中尋找截驮。
那么為什么這兩張圖都CPU呢笑陈?尤其我們知道,CPU葵袭,中央處理器嘛涵妥,按上面所說的分類,怎么著也應該是運算器和控制器坡锡,怎么也輪不到存儲器吧蓬网?但實際上CPU中也有一個存儲的空間,叫做寄存器鹉勒。我們都知道帆锋,馮諾依曼計算機思想的中心原則就是指令和數(shù)據(jù)一起存儲,那么作為一條指令禽额,在CPU上運行锯厢,它的存儲在哪里?為了提升這種在運算中的數(shù)據(jù)和指令的存取速度,所以有了寄存器实辑,這些正在運算中的指令與數(shù)據(jù)就存在了寄存器之上臣疑。
既然我們今天想要討論內(nèi)存,那就聚焦于內(nèi)存之上徙菠,這其中會涉及到很多有關內(nèi)存的分段讯沈,分頁,缺頁中斷算法等理論婿奔,這些與我們要討論的堆棧無關缺狠,但是其實還是可以講一下(或者挖個坑)。
說完了這些我們可以再稍微明確一下堆棧是什么萍摊,簡單來說挤茄,堆棧只是兩個數(shù)據(jù)結(jié)構,這一點其實再上一篇中已經(jīng)簡單提到了冰木,那么為什么我們再計算機運算穷劈,存儲的過程中反復提到了堆棧的概念呢?因為踊沸,堆棧是在進行內(nèi)存管理中的重要概念歇终,內(nèi)存的存儲方式實際上就是一塊一塊的地址,而堆與棧就是通過程序員主動或者程序自動的方式逼龟,為數(shù)據(jù)分配相應的地址空間评凝。
在寫程序的時候,我們知道棧與堆最重要的區(qū)別就是:棧是由編譯器自動分配的腺律,其中存儲的是函數(shù)的參數(shù)值奕短,局部變量的值等;堆是由程序員自己主動分配的匀钧,每當新建一個變量翎碑,會在堆中新開辟一塊地址區(qū)域。這樣說其實比較籠統(tǒng)之斯,也不夠準確日杈,因為,本身當我們?nèi)ew一個變量的時候吊圾,它也會有賦值操作达椰,也會有調(diào)用函數(shù),那它不是既存在于堆中项乒,又存在于棧中了么啰劲?
所以,其實那樣對于堆棧的解釋不夠準確檀何,其實這樣的解釋并不矛盾的蝇裤。因為棧之中廷支,存在的是新建的變量的一個地址的引用,而堆中存在的是這個引用變量的真實地址栓辜,其內(nèi)部是該變量的真實內(nèi)容恋拍。所以當數(shù)據(jù)改變的時候,實際上是改變了這個地址的引用藕甩,所以存在堆中的引用變量也會改變施敢,這也就涉及到了深淺復制的問題。(見http://www.reibang.com/p/65bf223bbba9)
那么這樣嚴格來說狭莱,好像計算機內(nèi)存于堆棧是完全沒有什么關系的東西僵娃,但是或許是他們的結(jié)構類似吧,也有相似的映射關聯(lián)腋妙,內(nèi)存有與具體文件的映射關系默怨,而棧是和堆之間有映射關系,而且我們常常對于內(nèi)存會有列狀的地址欄表示骤素,與棧的結(jié)構會有所相似匙睹,但是實際上在內(nèi)存分配的大部分時候是不連續(xù)且隨機的,并不具有棧那么規(guī)則的結(jié)構济竹,其中會有內(nèi)存的碎片痕檬,這與棧和堆也是完全不類似且沒什么聯(lián)系的。
唯一我們需要知道的就是规辱,棧和堆中的內(nèi)容都是有地址的谆棺,棧內(nèi)存中變量都是有地址的栽燕,無論是直接字面量罕袋,還是變量,還是地址的引用碍岔,都是有獨立的地址的浴讯,尤其是地址的引用這里需要注意,這個變量有自己單獨的地址蔼啦,與在堆中的引用變量是完全不同且沒有任何直接關系的地址榆纽,堆中的引用變量自然也有自己獨立的地址,這些數(shù)據(jù)都存在內(nèi)存之上捏肢,一部分在緩存之中奈籽,當CPU處理的時候會將他們放到寄存器之上。在基礎之上鸵赫,大概就是這樣了衣屏,如果需要再了解一些棧幀,地址方向等知識辩棒,我感覺自己還需要再準備一下狼忱,仔細了解一下內(nèi)存的構造膨疏。