1. 程式人生 > >C語言 malloc/free和C++中new/delete的區別

C語言 malloc/free和C++中new/delete的區別

1. malloc()函式
1.1 malloc的全稱是memory allocation,中文叫動態記憶體分配。
原型:extern void *malloc(unsigned int num_bytes); 
說明:分配長度為num_bytes位元組的記憶體塊。如果分配成功則返回指向被分配記憶體的指標,分配失敗返回空指標NULL。當記憶體不再使用時,應使用free()函式將記憶體塊釋放。

1.2 void *malloc(int size); 
說明:malloc 向系統申請分配指定size個位元組的記憶體空間,返回型別是 void* 型別。void* 表示未確定型別的指標。C,C++規定,void* 型別可以強制轉換為任何其它型別的指標。   
備註:void* 表示未確定型別的指標,更明確的說是指申請記憶體空間時還不知道使用者是用這段空間來儲存什麼型別的資料(比如是char還是int或者...)

1.3 free
void free(void *FirstByte): 該函式是將之前用malloc分配的空間還給程式或者是作業系統,也就是釋放了這塊記憶體,讓它重新得到自由。

1.4注意事項
1)申請了記憶體空間後,必須檢查是否分配成功。

2)當不需要再使用申請的記憶體時,記得釋放;釋放後應該把指向這塊記憶體的指標指向NULL,防止程式後面不小心使用了它。

3)這兩個函式應該是配對。如果申請後不釋放就是記憶體洩露;如果無故釋放那就是什麼也沒有做。釋放只能一次,如果釋放兩次及兩次以上會出現錯誤(釋放空指標例外,釋放空指標其實也等於啥也沒做,所以釋放空指標釋放多少次都沒有問題)。

4)

雖然malloc()函式的型別是(void *),任何型別的指標都可以轉換成(void *),但是最好還是在前面進行強制型別轉換,因為這樣可以躲過一些編譯器的檢查。

1.5  malloc()到底從哪裡得到了記憶體空間?
答案是從堆裡面獲得空間。也就是說函式返回的指標是指向堆裡面的一塊記憶體。作業系統中有一個記錄空閒記憶體地址的連結串列。當作業系統收到程式的申請時,就會遍歷該連結串列,然後就尋找第一個空間大於所申請空間的堆結點,然後就將該結點從空閒結點連結串列中刪除,並將該結點的空間分配給程式。

2. new運算子

2.1 C++中,用new和delete動態建立和釋放陣列或單個物件。
動態建立物件時,只需指定其資料型別,而不必為該物件命名,new表示式返回指向該新建立物件的指標,我們可以通過指標來訪問此物件。
int *pi=new int;
這個new表示式在堆區中分配建立了一個整型物件,並返回此物件的地址,並用該地址初始化指標pi 。

2.2 動態建立物件的初始化
動態建立的物件可以用初始化變數的方式初始化。
int *pi=new int(100); //指標pi所指向的物件初始化為100
string *ps=new string(10,'9');//*ps 為“9999999999”

如果不提供顯示初始化,對於類型別,用該類的預設建構函式初始化;而內建型別的物件則無初始化。
也可以對動態建立的物件做值初始化:
int *pi=new int( );//初始化為0
int *pi=new int;//pi 指向一個沒有初始化的int
string *ps=new string( );//初始化為空字串 (對於提供了預設建構函式的類型別,沒有必要對其物件進行值初始化)

2.3 撤銷動態建立的物件
delete表示式釋放指標指向的地址空間。
delete pi ;// 釋放單個物件
delete [ ]pi;//釋放陣列
如果指標指向的不是new分配的記憶體地址,則使用delete是不合法的。

2.4 在delete之後,重設指標的值
delete p; //執行完該語句後,p變成了不確定的指標,在很多機器上,儘管p值沒有明確定義,但仍然存放了它之前所指物件的地址,然後p所指向的記憶體已經被釋放了,所以p不再有效。此時,該指標變成了懸垂指標(懸垂指標指向曾經存放物件的記憶體,但該物件已經不存在了)。懸垂指標往往導致程式錯誤,而且很難檢測出來。
一旦刪除了指標所指的物件,立即將指標置為0,這樣就非常清楚的指明指標不再指向任何物件。(零值指標:int *ip=0;)

2.5 區分零值指標和NULL指標
零值指標,是值是0的指標,可以是任何一種指標型別,可以是通用變體型別void*也可以是char*,int*等等。
空指標,其實空指標只是一種程式設計概念,就如一個容器可能有空和非空兩種基本狀態,而在非空時可能裡面儲存了一個數值是0,因此空指標是人為認為的指標不提供任何地址訊息。

2.6 new分配失敗時,返回什麼?
1993年前,c++一直要求在記憶體分配失敗時operator   new要返回0,現在則是要求operator   new丟擲std::bad_alloc異常。很多c++程式是在編譯器開始支援新規範前寫的。c++標準委員會不想放棄那些已有的遵循返回0規範的程式碼,所以他們提供了另外形式的operator   new(以及operator   new[])以繼續提供返回0功能。這些形式被稱為“無丟擲”,因為他們沒用過一個throw,而是在使用new的入口點採用了nothrow物件: 
class   widget   {   ...   };

widget   *pw1   =   new   widget;//   分配失敗丟擲std::bad_alloc  

if   (pw1   ==   0)   ... //   這個檢查一定失敗

widget   *pw2   =   new   (nothrow)   widget;   //   若分配失敗返回0

if   (pw2   ==   0)   ... //   這個檢查可能會成功

3. malloc和new的區別

3.1 new 返回指定型別的指標,並且可以自動計算所需要大小。
比如:   
1)
 int *p;   
p = new int; //返回型別為int* 型別(整數型指標),分配大小為 sizeof(int);   
或:   
int* parr;   
parr = new int [100]; //返回型別為 int* 型別(整數型指標),分配大小為 sizeof(int) * 100;   

2) 而 malloc 則必須要由我們計算位元組數,並且在返回後強行轉換為實際型別的指標。   
int* p;   
p = (int *) malloc (sizeof(int)*128);//分配128個(可根據實際需要替換該數值)整型儲存單元,並將這128個連續的整型儲存單元的首地址儲存到指標變數p中  
double *pd=(double *) malloc (sizeof(double)*12);//分配12個double型儲存單元,並將首地址儲存到指標變數pd中

3.2 malloc 只管分配記憶體,並不能對所得的記憶體進行初始化,所以得到的一片新記憶體中,其值將是隨機的。
除了分配及最後釋放的方法不一樣以外,通過malloc或new得到指標,在其它操作上保持一致。

4.有了malloc/free為什麼還要new/delete?
1)
 malloc與free是C++/C語言的標準庫函式,new/delete是C++的運算子。它們都可用於申請動態記憶體和釋放記憶體。

2) 對於非內部資料型別的物件而言,光用maloc/free無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行解構函式。由於malloc/free是庫函式而不是運算子,不在編譯器控制權限之內,不能夠把執行建構函式和解構函式的任務強加於malloc/free。

因此C++語言需要一個能完成動態記憶體分配和初始化工作的運算子new,以及一個能完成清理與釋放記憶體工作的運算子delete。注意new/delete不是庫函式。

我們不要企圖用malloc/free來完成動態物件的記憶體管理,應該用new/delete。由於內部資料型別的“物件”沒有構造與析構的過程,對它們而言malloc/free和new/delete是等價的。

3) 既然new/delete的功能完全覆蓋了malloc/free,為什麼C++不把malloc/free淘汰出局呢?這是因為C++程式經常要呼叫C函式,而C程式只能用malloc/free管理動態記憶體。

如果用free釋放“new建立的動態物件”,那麼該物件因無法執行解構函式而可能導致程式出錯。如果用delete釋放“malloc申請的動態記憶體”,結果也會導致程式出錯,但是該程式的可讀性很差。所以new/delete必須配對使用,malloc/free也一樣。

相關推薦

C語言 malloc/freeC++new/delete區別

1. malloc()函式1.1 malloc的全稱是memory allocation,中文叫動態記憶體分配。原型:extern void *malloc(unsigned int num_bytes); 說明:分配長度為num_bytes位元組的記憶體塊。如果分配成功

C語言中malloc/freeC++new/delete區別

1. malloc()函式1.1 malloc的全稱是memory allocation,中文叫動態記憶體分配。原型:extern void *malloc(unsigned int num_bytes); 說明:分配長度為num_bytes位元組的記憶體塊。如果分配成功則返回指向被分配記憶體的指標,分配失敗

淺析C語言auto關鍵字C++ 的auto關鍵字

      最近在讀《C++ Prime》,不禁想感嘆一句:C++真是一種美麗的語言!!!!!!!      C++提供了相比於 C語言更加豐富的庫函式,功也更加強大。舉個例子吧。      題目:編寫一段程式,讀入一段包含標點符號的字串,將標點符號去除後輸出字串剩餘的部分。

C語言INT64型別GCC的long long的定義,及sprintf格式字串的定義

d,lx,ld,,lu,這幾個都是輸出32位的 hd,hx,hu,這幾個都是輸出16位資料的, hhd,hhx,hhu,這幾個都是輸出8位的, lld,ll,llu,llx,這幾個都是輸出64位的, printf( "%llu ",.....) %llu  是64位無符號 %llx才是64位16進位制數

C語言結構體C++類的區別

1.C的結構體和C++結構體的區別 1.1 C的結構體內不允許有函式存在,C++允許有內部成員函式,且允許該函式是虛擬函式。所以C的結構體是沒有建構函式、解構函式、和this指標的。 1.2 C的結構體對內部成員變數的訪問許可權只能是public,而C++允許public,protec

C++分析NewDelete----C語言MallocFree

C++中為什麼不用Malloc和Free,而用New和Delete?   <1> 如圖: 類的物件在堆上分配的時候用malloc和free: 我們觀察發現雖然在堆上申請空間了,但並沒有呼叫

C++malloc/freenew/delete區別---補充(15)《Effective C++》

1、C++中既然有了new/delete為什麼還有還存在malloc/free呢? 1)malloc/free作為C/C++語言中的庫函式,而new/delete是C++中的運算子而已,因此C++編譯器可以強制使new/delete運算子進行建構函式和解構函式

關於c語言內存分配,malloc,free,段錯誤,內存泄露

今天 text new .net 決定 析構函數 靈活 如果 best 1. C語言的函數malloc和free (1) 函數malloc和free在頭文件<stdlib.h>中的原型及參數 void * malloc(size_t size

C/C++ - malloc/freenew/delete的區分

字節 delete 分別是 自定義 void int eight 構造函數 內存 new/delete與malloc/free的區別主要表現在以下幾個方面:   註意:最主要的區別,new/delete是運算符,而malloc/free是函數   (1)、new能夠自動計算

C語言中的malloc/freeC++new/delete區別

有以下不同: (1)new、delete 是操作符,可以過載,只能在C++中使用。(2)malloc、free是函式,可以覆蓋,C、C++中都可以使用。(3)new 可以呼叫物件的建構函式,對應的de

C語言學習筆記 (003) - C/C++的實參形參(轉)

變化 避免 影響 學習筆記 ++ nbsp 過去 情況 真的 今天突然看到一道關於形參和實參的題,我居然不求甚解。藐視過去在我的腦海裏只有一個參數的概念,對於形參和實參的區別還真的不知道,作為學習了幾年C++的人來說,真的深深感覺對不起自己對不起C++老師 T。T 我

C語言的的freec++的delete區別

表示 log 一個數 重復 csdn 應用 malloc null 析構 首先free對應的是malloc;delete對應的是new;free用來釋放malloc出來動態內存,delete用來釋放new出來的動態內存空間。 應用的區別為: 1. 數組的時候int *p=(

c語言 將一個數組的奇數偶數分開放在一起

       在一個數組中的元素大多奇數和偶數是混在一起的,而將陣列中元素奇數和偶數分開存放則是我們要解決的問題。        將奇數和偶數分開存放然後打印出來的思路是先建立兩個空間,將奇數和偶數分別存放起來,然後

C語言mallocC++裡面new的對比

int *p=new int; //開闢一個存放整型資料的儲存空間,同時返回指向一個該空間的地址((int*)型,就是一個指標) new int (100); //開闢一個存放整型資料的儲存空間,同時返回指向一個該空間的地址,

關於C++new/deletenew[]/delete[]

參看連結 淺談 C++ 中的 new/delete 和 new[]/delete[] operator new 和 operator delete 這兩個其實是 C++ 語言標準庫的庫函式,原型分別如下: void *operator new(size_t); //al

[c語言]codeday15找出陣列出現一次的兩個值以及喝汽水模擬實現strcpy

1.一個數組中只有兩個數字是出現一次, 其他所有數字都出現了兩次。 找出這兩個數字,程式設計實現 #include<stdio.h> void find(int arr[],int len,int *m,int *n) { int s = 0;

c語言中指針多維數組的理解

分享 方式 方括號 mage 維數 jpg 聲明 col 多維數組 1.復習指針和數組之間的特殊關系:不帶方括號的數組名是一個指針,指向該數組的第一個元素。 2.多維數組: int multi[2][4];//聲明一個二維數組作為舉例 a.理解方式1:可以將數組看成行

C語言學習】《C Primer Plus》第8章 字符輸入/輸出輸入確認

multipl 字符輸入 信號 first while 目的 bcd 問題 img 學習總結 1、緩沖區分為完全緩沖區(fully buffered)I/O和行緩沖區(line-buffered)I/O。對完全緩沖輸入來說,當緩沖區滿的時候會被清空(緩沖區內容發送至

C語言的結構聯合,以及PHP是怎麽實現弱類型的

main 中一 字符 變量類型 type 以及 logs void 例子   C語言的結構(struct):包含多個成員,可能有多種數據類型,並且需要分配幾種類型占用空間之和的空間。   聯合(union):支持多種類型,供使用者使用其中一種數據類型,當然是需要分配其中占用

C語言在linux內核do while(0)妙用之法

pos turn jsb world div fprintf cpp efault code 為什麽說do while(0) 妙?由於它的確就是妙,並且在linux內核中實現是相當的妙,我們來看看內核中的相關代碼: #define db_error(fmt, ..