天天看點

new與malloc的差別

new配置設定記憶體按照資料類型進行配置設定,malloc配置設定記憶體按照大小配置設定; new不僅配置設定一段記憶體,而且會調用構造函數,但是malloc則不會。new的實作原理?但是還需要注意的是,之前看到過一個題說int p = new int與int p = new int()的差別,因為int屬于C++内置對象,不會預設初始化,必須顯示調用預設構造函數,但是對于自定義對象都會預設調用構造函數初始化。翻閱資料後,在C++11中兩者沒有差別了,自己測試的結構也都是為0; new傳回的是指定對象的指針,而malloc傳回的是void*,是以malloc的傳回值一般都需要進行類型轉化; new是一個操作符可以重載,malloc是一個庫函數; new配置設定的記憶體要用delete銷毀,malloc要用free來銷毀;delete銷毀的時候會調用對象的析構函數,而free則不會; malloc配置設定的記憶體不夠的時候,可以用realloc擴容。擴容的原理?new沒用這樣操作;

realloc是從堆上配置設定記憶體的.當擴大一塊記憶體空間時,realloc()試圖直接從堆上現存的資料後面的那些位元組中獲得附加的位元組,如果能夠滿足,自然天下太平;如果資料後面的位元組不夠,那麼就使用堆上第一個有足夠大小的自由塊,現存的資料然後就被拷貝至新的位置,而老塊則放回到堆上.這句話傳遞的一個重要的資訊就是資料可能被移動.

  1. int len =7;  
  2. int * a = (int *) malloc (sizeof(int) * len);  
  3. len++;  
  4. int * aold = a;            //重新配置設定前儲存a的位址  這個是多餘的  
  5. a = (int *)realloc(sizeof(int)* len);   //重新配置設定28+4 = 32位元組記憶體給數組a  

    前面兩句定義了1個長度為7的int 類型數組, 每個元素的位元組長度是4, 是以共占28byte 記憶體.

    第3句長度變量+1

    第4句 分兩種情況:

       1) 假如數組a 記憶體裡接着的4個位元組還沒被其他對象或程式占用, 那麼就直接把後面4個位元組加給數組a, 數組前面7個舊的元素的值不變,  數組a的頭部位址也不變.

       2) 假如數組 a記憶體裡接着的4個位元組已經被占用了, 那麼realloc 函數會在記憶體其他地方找1個連續的32byte 記憶體空間, 并且把數組a的7個舊元素的值搬過去,  是以數組a的7個舊元素的值也不變, 但是數組a的頭部位址變化了.  但是這時我們無需手動把舊的記憶體空間釋放. 因為realloc 函數改變位址後會自動釋放舊的記憶體, 再手動釋放程式就會出錯了

new如果配置設定失敗了會抛出bad_alloc的異常,而malloc失敗了會傳回NULL。是以對于new,正确的姿勢是采用try...catch文法,而malloc則應該判斷指針的傳回值。為了相容很多c程式員的習慣,C++也可以采用new(nothrow) 的方法禁止抛出異常而傳回NULL:

[cpp]  view plain  copy

  1. #include <new>//必須使用new頭檔案  
  2. Manager * pManager = new (nothrow) Manager();  
  3. if(NULL == pManager)  
  4. {  
  5.     //記錄日志  
  6.     return false;  
  7. }  

[cpp]  view plain  copy

  1. void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)  
  2.         {       // try to allocate size bytes  
  3.         void *p;  
  4.         while ((p = malloc(size)) == 0)  
  5.                 if (_callnewh(size) == 0)  
  6.                 {       // report no memory  
  7.                         _THROW_NCEE(_XSTD bad_alloc, );  
  8.                 }  
  9.         return (p);  
  10.         }  

調用malloc失敗後會調用_callnewh。如果_callnewh傳回0則抛出bac_alloc異常,傳回非零則繼續配置設定記憶體。 _callnewh是 一個new handler,通俗來講就是new失敗的時候調用的回調函數。可以通過_set_new_handler來設定。

new和new[]的差別,new[]一次配置設定所有記憶體,多次調用構造函數,分别搭配使用delete和delete[],同理,delete[]多次調用析構函數,銷毀數組中的每個對象。而malloc則隻能sizeof(int) * n;如果不夠可以繼續談new和malloc的實作,空閑連結清單,配置設定方法(首次适配原則,最佳适配原則,最差适配原則,快速适配原則)。delete和free的實作原理,free為什麼知道銷毀多大的空間?

new與malloc的差別

繼續閱讀