一、區別
注:首先堆和棧可以分為兩種,一種是數據結構,另一種是和內存的分配有關,這兩種雖然都有棧和堆,但是兩者關系並不大,
1、棧、堆是數據結構里面的叫法,注意:有時候有人喜歡這樣說 “堆棧” 其實說的就是棧而不是堆。
2、棧區、堆區 則是內存模型的叫法。

二、內存中的棧區和堆區
我們知道php的底層是C (任何語言其實都可以分為大同小異的幾塊)
而C語言的內存模型分為5個區:棧區、堆區、靜態區、常量區、代碼區。每個區存儲的內容如下:
1、棧區:存放函數的參數值、局部變量等,由編譯器自動分配和釋放,通常在函數執行完后就釋放了,其操作方式類似於數據結構中的棧。棧內存分配運算內置於CPU的指令集,效率很高,但是分配的內存量有限,比如iOS中棧區的大小是2M。
2、堆區:就是通過new、malloc、realloc分配的內存塊,編譯器不會負責它們的釋放工作,需要用程序區釋放。分配方式類似於數據結構中的鏈表。“內存泄漏”通常說的就是堆區。
3、靜態區:全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。程序結束后,由系統釋放。
4、常量區:常量存儲在這里,不允許修改。
5、代碼區:顧名思義,存放代碼。
分布圖:

棧區和堆區大小差異?
棧區:由圖中其實可以知道,棧區是向低地址擴展的,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,大小在進程分配時是確定的,具體大小看編譯器,操作系統。所需大小一般小於10M!太大沒有意義,不符合棧是用來快速存取的目標。
堆區:堆區是向高地址擴展的,是不連續的內存區域(這是由於系統是用鏈表來存儲的空閑內存地址的,自然是不連續的是動態分配的),因為會手動進行分配,會大一些,大小不固定。
棧區和堆區效率差異?
棧區:由系統自動分配,速度較快。但程序員是無法控制的。(只要棧的剩余空間大於所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。)
堆區:是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便。(首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然后將該結點從空閑結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的 delete語句才能正確的釋放本內存空間。另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多余的那部分重新放入空閑鏈表中)
小結:其實從上面的知識我們可以看出,如果存放在堆中的數據如果不進行釋放,很可能造成內存泄漏,因為並不一定能觸發gc機制回收。所以對於堆中的內存使用,我們要記得用完釋放。

三、數據結構中的棧和堆
什么是數據結構?
存儲與組織數據的方式。我感覺更應強調數據的組織方式,比如好多數據結構的存儲方式都是用的數組,但他們根據自身的特點進行了封裝,因為存儲方式只有順序存儲和鏈式存儲兩種,但是卻可以組合成多種數據結構。
常用的數據結構有哪些?
數組、棧、堆、隊列、鏈表等等。
棧
棧是限定僅僅在表尾進行插入和刪除操作的線性表,把允許插入和刪除的一端稱之為棧頂,另外一端稱之為棧底。特點:后進先出,稱之為后進先出線性表。
棧的應用:遞歸。
堆
是一種經過排序的樹形數據結構,每一個節點都有一個值,通常所說堆的數據結構是二叉樹,堆的存取是隨意的。所以堆在數據結構中通常可以被看做是一棵樹的數組對象。而且堆需要滿足一下兩個性質:
(1)堆中某個節點的值總是不大於或不小於其父節點的值;
(2)堆總是一棵完全二叉樹。
堆的應用:堆排序,快速找出最大值、最小值,簡化時間復雜度,像這樣支持插入元素和尋找最大(小)值元素的數據結構稱之為優先隊列。

最后,如果你也想成為程序員,想要快速掌握編程,趕緊加入學習企鵝圈子!
里面有資深專業軟件開發工程師,在線解答你的所有疑惑~編程語言入門“so easy”
編程學習書籍:

編程學習視頻:
