你就簡單的來理解就可以了 堆棧就是兩種存放數(shù)據(jù)的方式
不要new直接來定義的是棧 用new來定義的就是堆
首先來講解棧 棧的優(yōu)勢是,存取速度比堆要快。但缺點是缺乏靈活性
而堆測試速度慢 但是靈活性好
比如八大基本數(shù)據(jù)類型 在你int sum = 0;的時候 就是sum是一個指向int類型的引用,指向0這個字面值
你在頂一個 int i=0;他會去找有沒有0 有的話就會指向它 所以棧具有共享數(shù)據(jù)的特性
而當(dāng)你String str = new String("a");的時候 它就會在堆中建立一個對象
其實你就理解成兩種方式的存放數(shù)據(jù)的方式就行
簡單的說 其實 棧 就是存放變量引用的一個地方, 堆 就是存放實際對象的地方 也就是.
比如: int i = 7; 這個 其實是存在棧里邊的。內(nèi)容為 i = 7。
Apple app = new Apple(); 這個 app 是在棧里邊的 他對應(yīng)的是一個內(nèi)存地址也在堆里邊, 而這個內(nèi)存地址對應(yīng)的是堆里邊存放 Apple 實例的地址。
String s = "Hello World!"; 這個其實是存在另外一塊靜態(tài)代碼區(qū)。
總體來說: 棧--主要存放引用 和基本數(shù)據(jù)類型。
堆--用來存放 new 出來的對象實例。
Java中堆棧的概念是邏輯上的,在完全符合Java規(guī)范的Java處理器面世之前,所有Java虛擬機(jī)提供的內(nèi)容都是由軟件模擬出來的。
什么叫堆?你用十幾個麻將牌豎直疊成一摞這叫堆,你可以從上面、下面、中間任意抽出一張牌,也可以任意插入一張。
什么叫棧?AK-47的彈匣就是一個棧,在上面的子彈沒被取出之前,你無法取出下面的子彈——盡管你可以從邊上的透明部分讀出里面裝的是什么型號、顏色的子彈。
堆很靈活,但是不安全。對于對象,我們要動態(tài)地創(chuàng)建、銷毀,不能說后創(chuàng)建的對象沒有銷毀,先前創(chuàng)建的對象就不能銷毀,那樣的話我們的程序就寸步難行,所以Java中用堆來存儲對象。而一旦堆中的對象被銷毀,我們繼續(xù)引用這個對象的話,就會出現(xiàn)著名的 NullPointerException,這就是堆的缺點——錯誤的引用邏輯只有在運(yùn)行時才會被發(fā)現(xiàn)。
棧不靈活,但是很嚴(yán)格,是安全的,易于管理。因為只要上面的引用沒有銷毀,下面引用就一定還在,所以,在棧中,上面引用永遠(yuǎn)可以通過下面引用來查找對象,同時如果確認(rèn)某一區(qū)間的內(nèi)容會一起存在、一起銷毀,也可以上下互相引用。在大部分程序中,都是先定義的變量、引用先進(jìn)棧,后定義的后進(jìn)棧,同時,區(qū)塊內(nèi)部的變量、引用在進(jìn)入?yún)^(qū)塊時壓棧,區(qū)塊結(jié)束時出棧,理解了這種機(jī)制,我們就可以很方便地理解各種編程語言的作用域的概念了,同時這也是棧的優(yōu)點——錯誤的引用邏輯在編譯時就可以被發(fā)現(xiàn)。
在Java中,引用可以理解為一個永遠(yuǎn)指向?qū)ο蟮闹羔槪琂ava沒有指向指針的指針。
關(guān)于堆棧的資料幾乎每個講數(shù)據(jù)結(jié)構(gòu)的書上都有,而至于Java中堆、棧的具體機(jī)制你可以參考一些關(guān)于Java虛擬機(jī)原理的書,不過這個好像比較難理解,我是沒指望理解的了。
以上都是我的個人觀點,僅供參考。
內(nèi)存中的兩種存儲區(qū)
1..棧的特點是 容量小 速度快 適合存放小型數(shù)據(jù) 如基本數(shù)據(jù)類型和對象類型的引用
在棧中變量直接指向存放變量值的空間 對于對象引用則存放對象在堆中的內(nèi)存地址
2..堆的特點和棧相反 因此適合存放對象本身
3..對象引用訪問對象的原理是 先通過該引用找到棧中的數(shù)據(jù) 即對象的地址 在通過該
地址訪問對象 這就是為什么 對象 a=null; 調(diào)用a.方法(屬性) 會引發(fā)異常 因為找不到
實際對象的地址 向一個不存在的對象發(fā)送消息 如同叫一個不存在的人去幫你做事
程序不崩潰才怪
簡單的說:Java把內(nèi)存劃分成兩種:一種是棧內(nèi)存,一種是堆內(nèi)存。
在函數(shù)中定義的一些基本類型的變量和對象的引用變量都在函數(shù)的棧內(nèi)存中分配。當(dāng)在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內(nèi)存空間,當(dāng)超過變量的作用域后,Java會自動釋放掉為該變量所分配的內(nèi)存空間,該內(nèi)存空間可以立即被另作他用。
堆內(nèi)存用來存放由new創(chuàng)建的對象和數(shù)組。在堆中分配的內(nèi)存,由Java虛擬機(jī)的自動垃圾回收器來管理。在堆中產(chǎn)生了一個數(shù)組或?qū)ο蠛?,還可以在棧中定義一個特殊的變量,讓棧中這個變量的取值等于數(shù)組或?qū)ο笤诙褍?nèi)存中的首地址,棧中的這個變量就成了數(shù)組或?qū)ο蟮囊米兞俊R米兞烤拖喈?dāng)于是為數(shù)組或?qū)ο笃鸬囊粋€名稱,以后就可以在程序中使用棧中的引用變量來訪問堆中的數(shù)組或?qū)ο?/p>
堆棧是一種執(zhí)行“后進(jìn)先出”算法的數(shù)據(jù)結(jié)構(gòu)。
設(shè)想有一個直徑不大、一端開口一端封閉的竹筒。有若干個寫有編號的小球,小球的直徑比竹筒的直徑略小?,F(xiàn)在把不同編號的小球放到竹筒里面,可以發(fā)現(xiàn)一種規(guī)律:先放進(jìn)去的小球只能后拿出來,反之,后放進(jìn)去的小球能夠先拿出來。所以“先進(jìn)后出”就是這種結(jié)構(gòu)的特點。
堆棧就是這樣一種數(shù)據(jù)結(jié)構(gòu)。它是在內(nèi)存中開辟一個存儲區(qū)域,數(shù)據(jù)一個一個順序地存入(也就是“壓入——push”)這個區(qū)域之中。有一個地址指針總指向最后一個壓入堆棧的數(shù)據(jù)所在的數(shù)據(jù)單元,存放這個地址指針的寄存器就叫做堆棧指示器。開始放入數(shù)據(jù)的單元叫做“棧底”。數(shù)據(jù)一個一個地存入,這個過程叫做“壓?!?。在壓棧的過程中,每有一個數(shù)據(jù)壓入堆棧,就放在和前一個單元相連的后面一個單元中,堆棧指示器中的地址自動加1。讀取這些數(shù)據(jù)時,按照堆棧指示器中的地址讀取數(shù)據(jù),堆棧指示器中的地址數(shù)自動減 1。這個過程叫做“彈出pop”。如此就實現(xiàn)了后進(jìn)先出的原則。
堆棧是計算機(jī)中最常用的一種數(shù)據(jù)結(jié)構(gòu),比如函數(shù)的調(diào)用在計算機(jī)中是用堆棧實現(xiàn)的。
堆棧可以用數(shù)組存儲,也可以用以后會介紹的鏈表存儲。
下面是一個堆棧的結(jié)構(gòu)體定義,包括一個棧頂指針,一個數(shù)據(jù)項數(shù)組。棧頂指針最開始指向-1,然后存入數(shù)據(jù)時,棧頂指針加1,取出數(shù)據(jù)后,棧頂指針減1。
#define MAX_SIZE 100
typedef int DATA_TYPE;
struct stack
{
DATA_TYPE data[MAX_SIZE];
int top;
};
在C++中,內(nèi)存分成5個區(qū),他們分別是堆、棧、自由存儲區(qū)、全局/靜態(tài)存儲區(qū)和常量存儲區(qū)。
棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變量的存儲區(qū)。里面的變量通常是局部變量、函數(shù)參數(shù)等。
堆,就是那些由new分配的內(nèi)存塊,他們的釋放編譯器不去管,由我們的應(yīng)用程序去控制,一般一個new就要對應(yīng)一個delete。如果程序員沒有釋放掉,那么在程序結(jié)束后,操作系統(tǒng)會自動回收。
自由存儲區(qū),就是那些由malloc等分配的內(nèi)存塊,他和堆是十分相似的,不過它是用free來結(jié)束自己的生命的。
全局/靜態(tài)存儲區(qū),全局變量和靜態(tài)變量被分配到同一塊內(nèi)存中,在以前的C語言中,全局變量又分為初始化的和未初始化的,在C++里面沒有這個區(qū)分了,他們共同占用同一塊內(nèi)存區(qū)。
常量存儲區(qū),這是一塊比較特殊的存儲區(qū),他們里面存放的是常量,不允許修改(當(dāng)然,你要通過非正當(dāng)手段也可以修改,而且方法很多.
聲明:本網(wǎng)站尊重并保護(hù)知識產(chǎn)權(quán),根據(jù)《信息網(wǎng)絡(luò)傳播權(quán)保護(hù)條例》,如果我們轉(zhuǎn)載的作品侵犯了您的權(quán)利,請在一個月內(nèi)通知我們,我們會及時刪除。
蜀ICP備2020033479號-4 Copyright ? 2016 學(xué)習(xí)鳥. 頁面生成時間:2.943秒