C和C 區別2 new和delete

2021-09-25 10:21:29 字數 4255 閱讀 3864

(一)記憶體分布

乙個由c/c++編譯的程式占用的記憶體分為以下幾個部分: 

1、棧區(stack)— 由編譯器自動分配釋放 ,存放為執行函式而分配的區域性變數、函式引數、返回資料、返回位址等。其操作方式類似於資料結構中的棧。 

2、堆區(heap) — 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束 時可能由os** 。分配方式類似於鍊錶。 

3、全域性區(靜態區)(static)—存放全域性變數、靜態資料、常量。程式結束後由系統釋放。 

4、文字常量區 —常量字串就是放在這裡的。 程式結束後由系統釋放。 

5、程式**區—存放函式體(類成員函式和全域性函式)的二進位制**。

動態分配

在執行程式的過程中動態的分配或者**儲存空間的分配記憶體的方法。

例如:當我們在定義乙個陣列時,必須要用乙個常量來確定在編譯時分配多大的空間。但是在真正使用陣列時,我們才會知道我們需要多少記憶體空間,所以我們要根據程式的需要即時分配,這就牽扯到記憶體的動態開闢。

(二)c語言  malloc/free

void* malloc(size_t size);

開闢一塊長度為size的連續記憶體空間,返回型別為void型別的指標。需要強轉,空間申請的大小與形式,跟資料型別無關,它就是動態分配的一段位址。即malloc申請的空間是沒有型別概念的,最後賦給具體指向哪種型別的指標,僅需強制轉換到相應型別即可。 如果開闢失敗,則返回null指標。

void free(void* ptr);

free函式是來釋放動態開闢的記憶體的。

malloc和free要配套使用,如果沒有free則會造成記憶體洩漏。

malloc怎樣獲取位址作業系統中有乙個記錄空閒記憶體位址的鍊錶,當作業系統收到程式的申請時,就會遍歷鍊錶,malloc函式返回的指標是指向堆裡的一塊記憶體;不能初始化;記憶體不足是,返回null。   

(三)c++語言  new   delete

為什麼還需要new/delete呢?

由於malloc/free 是庫函式而不是運算子,不在編譯器控制許可權之內,不能夠自動地呼叫建構函式和析構函式。即無法滿足動態物件的要求。因此 c++語言需要乙個能完成動態記憶體分配和初始化工作的運算子new,以及乙個能完成清理與釋放記憶體工作的運算子delete。

new運算子不需要型別強轉;

new能否進行異常處理,使用更安全。

new 

new運算返回所分配記憶體單元的起始位址,所以需要把返回值儲存在乙個指標變數中。若分配不成功,返回null,並丟擲異常。 

new沒有為建立的物件命名,只能通過指標去訪問物件或者陣列。

delete 

delete 《指標變數》 

delete 《動態分配的陣列名》

new和delete必須配對使用。 

雖然程式結束後系統會自動釋放程式和其中資料所佔的記憶體空間,但是為了在程式執行過程中能夠重複使用有限的記憶體資源,防止系統產生記憶體洩漏,還是應該即時釋放不需要的動態分配的記憶體單元,以便系統能隨時對該記憶體單元進行分配。 

delete釋放記憶體,只是銷毀記憶體上的物件,但是指標仍然存在,仍然指向原來的記憶體,儲存原來空間的位址。所以我們應該在釋放之後將指標置空,以避免後面不小心解引用造成問題。

//變數

int* nnum = new int(5); //注意申請簡單變數,也必須使用指標形式

delete nnum; //釋放空間

nnum = null; //讓指標指向空指標,杜絕野位址

//一維陣列

int* nnum1 = new int[5];

delete nnum1; //釋放空間,記住與變數不同

nnum1 = null;

//二維陣列

int (*pl)[4] //必須點明列大小

pl = new int[3][4];

delete pl;

pl = null;

使用new操作符來分配物件記憶體時會經歷三個步驟: 

第一步:呼叫operator new 函式(對於陣列是operator new)分配一塊足夠大的,原始的,未命名的記憶體空間以便儲存特定型別的物件。 

第二步:編譯器執行相應的建構函式以構造物件,並為其傳入初值。 

第三步:物件構造完成後,返回乙個指向該物件的指標。

使用delete操作符來釋放物件記憶體時會經歷兩個步驟: 

第一步:呼叫物件的析構函式。 

第二步:編譯器呼叫operator delete(或operator delete)函式釋放記憶體空間。

總之來說,new/delete會呼叫物件的建構函式/析構函式以完成物件的構造/析構;而malloc則不會。

(二)new和malloc的區別

new是c++中的關鍵字,需要編譯器支援。,malloc是c和c++的標準庫函式,需要標頭檔案支援。他們都可以申請記憶體。

new操作符從自由儲存區上為物件動態分配記憶體空間,而malloc函式從堆上動態分配記憶體。

自由儲存區是c++基於new操作符的乙個抽象概念,凡是通過new操作符進行記憶體申請,該記憶體即為自由儲存區。而堆是作業系統中的術語,是作業系統所維護的一塊特殊記憶體,用於程式的記憶體動態分配,c語言使用malloc從堆上分配記憶體,使用free釋放已分配的對應記憶體。自由儲存區不等於堆,如上所述,布局new就可以不位於堆中。

使用new操作符申請記憶體分配時無須指定記憶體塊的大小,編譯器會根據型別資訊自行計算,而malloc則需要顯式地指出所需記憶體的尺寸。

new可以開闢記憶體並做初始化,初始化物件呼叫的是建構函式,delete釋放記憶體呼叫析構函式。malloc不能初始化,malloc只是單純的開闢記憶體,free是單純的釋放記憶體。

new記憶體分配失敗時,會丟擲bac_alloc異常。malloc分配記憶體失敗時返回null。

使用new操作符申請記憶體分配時無須指定記憶體塊的大小,編譯器會根據型別資訊自行計算。而malloc則需要顯式地指出所需記憶體的尺寸。

new操作符記憶體分配成功時,返回的是物件型別的指標,型別嚴格與物件匹配,無須進行型別轉換,故new是符合型別安全性的操作符。而malloc記憶體分配成功則是返回void * ,需要通過強制型別轉換將void*指標轉換成我們需要的型別。

new支援過載。malloc不能過載。(c語言就不支援過載)

new可以開闢常量記憶體 ;malloc不能

new可以呼叫malloc ;malloc不能呼叫new

(三)new和delete用法:

new用法:

1.     開闢單變數位址空間

1)new int;  //開闢乙個存放陣列的儲存空間,返回乙個指向該儲存空間的位址.int *a = new int 即為將乙個int型別的位址賦值給整型指標a. 

2)int *a = new int(5) 作用同上,但是同時將整數賦值為5

2.     開闢陣列空間

一維: int *a = new int[100];開闢乙個大小為100的整型陣列空間

二維: int **a = new int[5][6]

三維及其以上:依此類推.

一般用法: new 型別 [初值]

delete用法:

1. int *a = new int;

delete a;   //釋放單個int的空間

2.int *a = new int[5];

delete a; //釋放int陣列空間

要訪問new所開闢的結構體空間,無法直接通過變數名進行,只能通過賦值的指標進行訪問.

用new和delete可以動態開闢,撤銷位址空間.在程式設計序時,若用完乙個變數(一般是暫時儲存的陣列),下次需要再用,但卻又想省去重新初始化的功夫,可以在每次開始使用時開闢乙個空間,在用完後撤銷它.

delete /delete

delete是**new開闢出的單個物件指標指向的記憶體。

delete[ ]是**new[ ]開闢出的物件陣列指標指向大的記憶體。

new[ ]開闢陣列空間要多出4個位元組來存放陣列大小。

delete[ ]和new[ ]要配套使用。

C 中new和override區別

在c 中實現重寫方法,可以用new和override兩個關鍵字來實現,究竟他們之間有什麼區別呢?下面,我以例子來說明他們之間的微妙區別 public class grandclass 基類 public virtual void method 用virtual才可以在子類中用override,而ne...

C 中new和override區別

在c 中實現重寫方法,可以用new和override兩個關鍵字來實現,究竟他們之間有什麼區別呢?下面,我以例子來說明他們之間的微妙區別 public class grandclass 基類 public virtual void method 用virtual才可以在子類中用override,而ne...

c 中,new 和 override 的區別

一 在c 中,new這個關鍵字使用頻率非常高,主要有3個功能 a 作為運算子用來建立乙個物件和呼叫建構函式。b 作為修飾符。c 用於在泛型宣告中約束可能用作型別引數的引數的型別。在本文中,只具體介紹new作為修飾符的作用,在用作修飾符時,new關鍵字可以在派生類中隱藏基類的方法,也就說在使用派生類的...