c/c++ 堆與棧 malloc/free與new/delete

c++中內存分爲5個區,分別是堆,棧,自由存儲區,全局/靜態存儲器和常亮存儲區

棧,就是有編譯器在需要的時候分配,在不需要的時候自動清除的變量的存儲區,裏面的變量通常是局部變量,函數參數等

堆,就是那些有new分配的內存塊,他們的釋放編譯器不去管,有我們的應用程序去控制,一般一個new就要對應一個delete,如果程序員沒有釋放掉,那麼在程序借宿後,操作系統會自動回收

自由存儲區,就是那些有malloc等分配的內存塊,他和堆是十分相似的,不過它是用free來結束自己的生命的

全局/靜態存儲區,全局變量和靜態變量被分配到同一塊內存中,在以前的c語言中,全局變量又分爲初始化和未初始化(初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量與靜態變量在相鄰的另一塊區域,同時未被初始化的對象存儲區可以通過void* 來訪問和操縱,程序結束後由系統自行釋放),在c++裏面沒有這個分區了,他們共同佔用同一塊內存區

常量存儲區,這是一塊特殊的存儲區,他們裏面存放的是常量,不允許修改(當然你要是通過非正當手段也可以修改)




堆和棧的區別

管理方式不用:對於棧來講,是有編譯器自動管理,無需我們手工控制;對於堆來說,釋放工作有程序員控制,容易產生內存泄漏

空間大小:一般來講是32位系統下,堆內存可以達到4g空間,從這個角度來看堆內存幾乎是沒有什麼限制的,但是對於棧來說,一般都是有一定的空間大小的

碎片問題:對於堆來說,頻繁的new/delete勢必會造成內存空間的不連續,從而造成大量的碎片是的程序的效率降低,對於棧來說,不存在這個問題,因爲棧是先進後出的隊列,他們是如此一一對應,以至於永遠不可能有一個內存塊從棧中間彈出來,在他彈出之前,在他上面的後進的棧內容已經被彈出,

生長方向:對於堆來說,生長方向是向上的,也就是向着內存地址增加的方向;對於棧來講,他的方向是向下的,是向着內存地址減小的方向增大

分配方式:堆都是動態分配的,沒有靜態分佈的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如局部變量的分配,動態分配由malloc函數進行分配,但是棧的動態分配是和堆不同的,他的動態分配是有編譯器進行釋放,無需我們手工實現

分配效率:堆的效率比棧要低的多




malloc/free 與new/delete的區別

相同點:都可以申請動態內存和釋放內存

不同點:

操作對象不同:malloc/free是c/c++的標準庫函數,new/delete是c++的運算符。

用法不同:函數mallcoc原型 void * malloc(size_t size)

                         用malloc申請一塊長度爲length的整數類型的內存:int *p=(int* )malloc(sizeof(int)*length);

                         1:malloc 返回值爲void*。所以在調用malloc時要顯式的進行類型轉換,將void*轉換成所需要的指針類型

                          2:malloc函數本身並不識別要申請的內存是什麼類型,它只關心內存的總字節數

                     函數free的原型是 void free(void* memblock)


new建立的是一個對象,malloc分配的是一塊內存

new可以認爲是malloc加構造函數的執行,new出來的指針是直接帶類型信息的,而malloc返回的都是void*指針,new delete在實現上其實是調用了malloc,free的函數

對於非內部數據類型的對象而言,用malloc/free無法滿足動態對象的要求,對象在創建的用時要自動執行構造函數,對象在消亡之前要自動執行析構函數,而malloc/free是庫函數不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加於malloc/free,因此c++語言需要一個能完成動態分配和初始化工作的運算符new,和一個能完成清理與釋放內存工作的運算符delete


                       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章