內存區域:
由這張圖咱們能夠看到程序在內存中的分佈,不一樣的變量存放在不一樣的區域,而內核空間是用戶沒法進行讀寫的用來存儲有關的信息。
要注意棧向下生長,堆向上生長,堆棧相對而生,咱們今天主要談在堆上申請空間的相關知識,咱們知道在c語言中想要在堆上申請空間須要用到malloc、realloc、calloc這類函數,關於這些函數的相同與不一樣點你們能夠參考個人另外一篇博客。c++
在c++中咱們用心的關鍵字 new、delete完成對空間的申請和釋放。語法是也是定義一個指針變量接受開闢的地址,int p=new int;c++容許咱們對申請的空間初始化,只要在後面跟上(),()內爲要初始化的內容便可。同時也能夠用int p=new int[];的方式申請連續的內存空間,這種方式在釋放時的方式爲delete [] p;。ide
注意:在申請自定義類型時new和malloc是相似的,那麼意味着對於內置類型free和delete是能夠混合使用的,用new申請的空間用free釋放也不會出現什麼錯誤,而對於用戶自定義類型new和delete會分別調用構造函數和析構函數,而malloc和free則不會,malloc申請的是與對象大小相同的一塊內存空間,是不會構成對象的,因此咱們在申請和釋放空間時要注意配對!函數
咱們在這裏談談malloc的原理:咱們知道malloc申請大小爲10個字節的空間時系統會爲咱們申請大於十個字節的空間,大概申請來的空間是長這個樣子滴:
這也就是咱們在free的時候系統會知道free多少個字節,由於在這個相似於結構體的結構內最前面已經保存了咱們申請空間大小的數值了。指針
這兩個函數是new和delete在底層調用的函數,也就是這兩個函數爲咱們完成了內存的開闢和釋放。
咱們首先看看operator new這個函數:code
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) { // try to allocate size bytes void *p; while ((p = malloc(size)) == 0) if (_callnewh(size) == 0) { // report no memory // 若是申請內存失敗了,這裏會拋出bad_alloc 類型異常 static const std::bad_alloc nomem; _RAISE(nomem); } return (p); }
從這個函數咱們能夠看到底層也是經過malloc實現的,那麼malloc申請成功則直接返回,malloc申請失敗嘗試執行空間不足的應對措施,執行這個措施就會繼續申請,不然拋出異常。因此new函數通常都不會申請失敗。對象
咱們再來看operator delete這個函數:blog
void operator delete(void *pUserData) { _CrtMemBlockHeader * pHead; RTCCALLBACK(_RTC_Free_hook, (pUserData, 0)); if (pUserData == NULL) return; _mlock(_HEAP_LOCK); /* block other threads */ __TRY /* get a pointer to memory block header */ pHead = pHdr(pUserData); /* verify block type */ _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)); _free_dbg( pUserData, pHead->nBlockUse ); __FINALLY _munlock(_HEAP_LOCK); /* release other threads */ __END_TRY_FINALLY return; }
經過這個咱們知道底層也是經過free實現的就ok。內存
咱們再看看對於自定義類型new和delete的原理:
new的原理資源
最後的最後咱們再細談一下malloc和new的區別:
1.new是操做符、malloc是函數
2.new能夠完成對開闢空間的初始化、malloc則不能
3.malloc在使用時須要計算所開闢內存的大小(字節)並傳遞,而new只需跟上類型便可
4.malloc的返回值是void,因此要強制類型轉化,new後是類型則不須要。
5.malloc申請失敗會返回NULL,因此要進行判空,new不須要但須要捕獲異常
6.malloc和free不會調用構造和析構函數。get