如何正確理解棧和堆?

cookie-zhang發表於2019-03-30

前言

學過計算機的童鞋們都知道棧和堆,說實話大學的時候真沒好好聽講,也就知道個大概,今天就簡單的總結一下,淺談棧和堆,去了解一下我們們平時定義變數的時候,在計算機中是怎麼儲存的。

什麼是堆和棧?

堆和棧其實是兩種資料結構。堆疊都是一種資料項按序排列的資料結構,只能在一端(稱為棧頂(top))對資料項進行插入和刪除。堆疊是個特殊的儲存區,主要功能是暫時存放資料和地址。

堆和棧什麼區別?

  • 棧(作業系統):由作業系統自動分配釋放 ,存放函式的引數值和區域性變數的值等。其操作方式類似於資料結構中的棧。簡單的理解就是當定義一個變數的時候,計算機會在記憶體中開闢一塊儲存空間來存放這個變數的值,這塊空間就叫做棧,然而棧中一般存放的是基本型別資料,棧的特點是先進後出(或後進先出)
  • 堆(作業系統): 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收,分配方式倒是類似於連結串列。其實在堆中一般存放變數是一些物件型別

程式碼中去理解棧和堆?

話不多說,我們們先上一段簡單的程式碼,自己去思考一下會列印出什麼結果並且為什麼會列印這種結果?,在堆和棧中怎麼呈現的?,在看下面對應的解釋,這樣的話可能就更好的理解了。

        //1
	var a = 10;
	b = a;
	b += 20;
	alert(a);
	
	//2
	var obj = {
		name : "jack"
	};
	b = obj;
	b.name = "Lily";
	alert( obj.name );
	
	//3
	var arr = [1,2,3];
	brr = arr;
	brr[0] = 10;
	alert( arr[0] );
	
	//4
	var a = 20;
	function fun(a){
		a += 30; 
	}
	fun( a );   
	alert( a );
	
	//5
	var arr = [1,2,3];
	function fun(brr){
		brr[0] = 20;
	}
	fun(arr); 
	alert(arr[0]);
複製程式碼

上圖:

如何正確理解棧和堆?

對著這張圖就可以理解第一道題為什麼會列印10了,當你宣告一個變數,計算機會在棧中給你開闢一個記憶體空間去儲存這個變數,當你去改變b的時候,那也只是去改變了b,所以a空間的值是不會受到任何影響,所以第一道題會列印出來10。

繼續上圖:

如何正確理解棧和堆?

如何正確理解棧和堆?

上面說了棧中儲存的是基本型別的資料,如果是陣列,物件等這些呢?上面這個圖就能看出來,對應著第三道題看,如果定義一個arr = [1,2,3]。在棧中就會儲存一個地址,在堆中就會儲存對應地址的值,這個地址就會指向對應的資料,那這個地址在計算機中叫什麼呢?其實就是所謂的指標變數, brr = arr; 叫做地址傳值,你會發現brr在堆中是指向同一個位置,從而當你改變brr[0]的時候,arr[0]也是跟著改變了,所以第三那道題的答案也就出來了,不再是1而是10;所以這種地址傳值也就稱其為一改全改

補充

上面提到的一改全改不知道你在真正開發的時候想到的了什麼,那就是深拷貝和淺拷貝的問題,在開發中會經常遇到這種問題,關於拷貝你可以看看我的這篇文章,<--點這裡。

總結

以上講解自我感覺通俗易懂,沒有太多華麗的語言,看的舒服看得懂才是最重要的,如果你是做前端的,如果你是非計算機專業半道出家的我相信也是對你有多幫助的,當然還有更專業的講解。剩下得幾道題可以自己去對著思考思考了,如果能幫到你更好的理解關於堆和棧,請給我一個小小的贊作為鼓勵,我會更努力的寫文章。


相關文章