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言中 .h檔案.c檔案的區別

要理解.c檔案與.h檔案有什麼不同之處,首先需要弄明白編譯器的工作過程,一般說來編譯器會做以下幾個過程: 1.預處理階段 2.詞法與語法分析階段 3.編譯階段,首先編譯成純彙編語句,再將之彙編成跟CPU相關的二進位制碼,生成各個目標檔案 4.連線階段,將各個目標檔案中的各段程式碼進行絕對地址定位,生成跟特定平

C言中 .h檔案.c檔案的區別 (轉)

要理解.c檔案與.h檔案有什麼不同之處,首先需要弄明白編譯器的工作過程,一般說來編譯器會做以下幾個過程:1.預處理階段2.詞法與語法分析階段3.編譯階段,首先編譯成純彙編語句,再將之彙編成跟CPU相關的二進位制碼,生成各個目標檔案4.連線階段,將各個目標檔案中的各段程式碼進行絕對地址定位,生成跟特定平臺相關

C言中 malloc free

from:http://blog.sina.com.cn/s/blog_af1a77fa0102xceb.html 一、malloc()和free()的基本概念以及基本用法: 1、函式原型及說明: void *malloc(long NumBytes):該函式分配了NumBytes個位元

關於c言中mallocremalloc函式的分析

首先申明,這是本人第一次寫部落格,其目的僅僅是為了加強自己對知識點的掌握,為到達在本子上記筆記的效果 進入正題。對於malloc,它的作用就是為了動態分配空間,像c++中的new一樣。這裡就不說他們兩的區別了。malloc函式有這樣幾個特點。 1.分配的空間地址是連續的,

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

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

C言中的structtypedef struct<轉載>

對象 內部數據 編程 都是 內部 pre title HR 聲明 原文:http://www.nowamagic.net/librarys/veda/detail/1785 typedef為C語言的關鍵字,作用是為一種數據類型定義一個新名字。這裏的數據類型包括內部數據類

C言中malloc函數的理解

萬能 一個 函數 語言 就是 有一個 類型轉換 har 扯淡 在C語言中malloc函數主要是用在堆內存的申請上,使用malloc函數時,函數會返回一個void *類型的值,這個值就是你申請的堆內存的首地址;為什麽返回的地址是一個void *類型的地址呢?首先我們要先弄明白

C言中fstat statlstat 區別

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

c言中的getchar()EOF

一、getchar的兩點總結: 1.getchar是以行為單位進行存取的。 當用getchar進行輸入時,如果輸入的第一個字元為有效字元(即輸入是檔案結束符EOF,Windows下為組合鍵Ctrl+Z, Unix/Linux下為組合鍵Ctrl+D),那麼只有當最後一個輸入字元為換行符'\n'

C言中的staticextern

  怕原作者刪除,所以轉載過來! 原文地址:http://blog.csdn.net/keyeagle/article/details/6708077/          C語言程式碼是以檔案為單位來

C言中的atanatan2

在C語言的math.h或C++中的cmath中有兩個求反正切的函式atan(double x)與atan2(double y,double x)  他們返回的值是弧度 要轉化為角度再自己處理下。 前者接受的是一個正切值(直線的斜率)得到夾角,但是由於正切的規律性

C言中的naninf 的判斷使用

引言 在資料處理輸入輸出時,極有可能遇到資料讀入空值(極大、極小)、運算中分母為0或0.0,對0取對數等操作,這將產生nan或inf的產生。這篇博文旨在分析C/C++產生nan和inf的操作及判斷是否有nan或inf產生。 NAN的產生原因 nan: not a num

C言中的voidvoid*的定義及用法

void void最常見的用法,就是在函式中限定函式的引數和返回值的 void draw(void); 表明函式draw沒有引數也沒有返回值,void在別的的地方的應用我也沒見過; 實際上,如果把void 和int,char,double等型別放到一起理解的話,首先還是那

C言中的voidvoid指標-void*

void 關鍵字 當函式返回值為空時,可以使用void。 void empty(int a); 當函式引數列表為空時,可以使用void。 void empty(void

C言中malloc、calloc、realloc動態記憶體分配的理解

void* realloc(void* ptr, unsigned newsize); void* malloc(unsigned size); void* calloc(size_t numElements, size_t sizeOfElement); 都在stdlib.h函式庫內 它們的返回值都是請求系

C言中typedef structstruct的區別

typedef struct CLinkList {     int data;     struct CLinkList *next; }node; 上面的CLinkList是識別符號,node是變數型別(相當於(int,char等))。 這語句實際上完成兩

14.C言中time函式localtime獲取系統時間日期

C語言中time函式和localtime獲取系統時間和日期可以通過time()函式來獲得計算機系統當前的日曆時間(Calendar Time),處理日期時間的函式都是以本函式的返回值為基礎進行運算。1. time 函式 返回1970-1-1, 00:00:00以來經過的秒數 

C言中“陣列名”“&陣列名”

C語言中 陣列名 和 &陣列名 == 實驗環境 == 1. 編譯器:gcc 5.4.0 2. 作業系統:Ubuntu 16.04 x86_64 緣起 本以為此知識點我已熟練掌握,可是最近應用的時候還真給記混淆了。所以寫篇文章加深印象。 Sho

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

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