說說new 和 malloc()
熟悉c++的朋友應該都知道,c++提供給了程式設計師與硬體打交道的可能性,比如說記憶體管理。
一個高水平的c++程式設計師可以將c++程式的效能優化到極致,榨乾硬體資源。而現在我想說說與
記憶體管理有關的new 和 malloc()。
先說說malloc(),malloc是從C語言那裡繼承過來的一個函式 ,其用於分配一片記憶體,它的
返回結果是一個指向你所需求的記憶體的指標,其函式原型和使用例子如下:
/* 函式原型 其中__size是你要分配的大小,其單位是byte */ void* malloc(size_t __size); // 用例 int* pInt = (int*) malloc(sizeof(int)); // 分配了一個int double* pDoubleArray = (double*) malloc(sizeof(double) * 5); // 分配了一個double陣列,其大小為5
一般來說,malloc總是能為你分配出記憶體。但是也存在山窮水盡,記憶體不夠用的情況。這時候
malloc會返回一個空指標(NULL, nullptr)。當你使用malloc的時候,你最好每次都要判斷一下返回的
指標是否為空。
現在記憶體已經分配出來了。當程式執行到某一些時刻,我又不想要這些記憶體了。這時候我們就要
手動釋放記憶體,否則的話就會造成記憶體洩露。通過free() 函式來釋放記憶體,其函式原型和使用例子如下:
// 原型 void free(void* __ptr); // 用例 free(pInt); free(pDoubleArray);
有趣的是你傳給free函式的只是一個指標,然而不管你是分配了一個元素還是分配了一個數組,
free總能幫你釋放掉這些記憶體(free 怎麼知道你分配的陣列的大小?)
讓我來詳細的說說malloc在分配記憶體的時候幹了什麼。malloc在分配記憶體的時候,不僅僅會分配
你需要的記憶體大小,它還會在你的記憶體的頭部和尾部加上一些額外的資訊(俗稱cookie )。比如說用
來DEBUG的資訊和你的記憶體的大小。這就解釋了為什麼能free掉你的記憶體,因為它知道你這塊記憶體是
多大的。值得一提的是這些Cookie會佔用一些記憶體。。。
好了,malloc已經介紹的差不多了。還想說的一點是malloc只是一個第三方的函式,並不是操作
系統的核心函式。如果有額外的需求的話,你可以設計自己的malloc。接下來談談new。
new是c++提供的一個操縱符(或者說關鍵字)。其也是用於分配記憶體的。其用例如下:
int* pInt = new int(3); // 分配並構造一個int double* pDoubleArray = new double[5]; // 分配了一個double陣列,其大小是5 delete pInt; // 刪除單元素 delete[] pDoubleArray; // 刪除陣列
還是老話題,一般來說程式是能為你分配出記憶體的,但是實在山窮水盡了怎麼辦?這時候程式就會
丟擲一個std::bad_alloc異常。注意,這是new 和 malloc 的區別之一。但是難能可貴的是C++提供了
一個機制來處理bad_alloc異常,其做法如下:
void BadAllocateHandler() { std::cout << "啊,記憶體分配失敗了" << std::endl; exit(0); } std::set_new_handler(BadAllocateHandler);
BadAllocateHandler是程式設計師自己寫的當分配失敗時的處理函式。而set_new_handler是c++提供的
機制。一般來說當山窮水盡的時候你所應該做的事只有兩件。要麼讓程式退出,要麼想辦法從別的地方
挖一些記憶體來繼續分配。
你已經知道了new是一個關鍵字。對於一個程式來說,一切的動作都將回到函式呼叫。所以new的時候
到底發生了什麼呢?當你new的時候,首先程式會去呼叫 ::operator new() 這個函式。然後 ::operator new()
中程式會去呼叫malloc()。 喔!一切都明瞭了,原來new的本質也是去呼叫malloc函式!!同理,delete的本
質是去呼叫free()函式。
雖然new的本質是去呼叫malloc,但是new 和 malloc還有一點很大的不同。那就是new 出來記憶體後,new
會幫你把物件給構造出來,而malloc只是分配記憶體。具體例子如下:
class MyObj { public: public MyObj(int value) : val(value) {} int val; }; MyObj* obj = new MyObj(4); MyObj* obj1 = (MyObj*) malloc(sizeof(MyObj));
new 的做法是在malloc分配出記憶體後,編譯器會直接呼叫類的建構函式在這片記憶體中構造出物件。注意!
只有編譯器能直接呼叫類的建構函式。而你使用malloc的話,是無法直接在上面構造出物件的。
好了。new和malloc說的差不多了,接下來要說說記憶體管理以及記憶體池相關的知識,詳情參見另一篇博文。