1. 程式人生 > 其它 >C++ new 和 malloc 的區別

C++ new 和 malloc 的區別

C++ new 和 malloc 的區別

1.記憶體位置

new操作符從自由儲存區(free store)上為物件動態分配記憶體空間,而malloc函式從堆上動態分配記憶體。自由儲存區是C++基於new操作符的一個抽象概念,凡是通過new操作符進行記憶體申請,該記憶體即為自由儲存區。而堆是作業系統中的術語,是作業系統所維護的一塊特殊記憶體,用於程式的記憶體動態分配,C語言使用malloc從堆上分配記憶體,使用free釋放已分配的對應記憶體。

那麼自由儲存區是否能夠是堆(問題等價於new是否能在堆上動態分配記憶體),這取決於operator new 的實現細節。自由儲存區不僅可以是堆,還可以是靜態儲存區,這都看operator new在哪裡為物件分配記憶體。

2.返回型別

new操作符記憶體分配成功時,返回的是物件型別的指標,型別嚴格與物件匹配,無須進行型別轉換,故new是符合型別安全性的操作符。

3.分配失敗處理

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

4.呼叫建構函式

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

第一步:呼叫operator new 函式(對於陣列是operator new[])分配一塊足夠大的,原始的,未命名的記憶體空間以便儲存特定型別的物件。
第二步:編譯器執行相應的建構函式以構造物件,併為其傳入初值。
第三部:物件構造完成後,返回一個指向該物件的指標。

5.呼叫解構函式

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

第一步:呼叫物件的解構函式。
第二步:編譯器呼叫operator delete(或operator delete[])函式釋放記憶體空間。

綜合實踐

程式碼

#include <iostream>
#include <cstdlib>
#include <limits.h>

#define N 10
using namespace std;

int main()
{
	// 區別1. malloc 必須強制轉換指標型別, 而 new 不用
	int * p = (int *)malloc(N * sizeof(int));
	int * q = new int[N];
	delete [] q;
	free(p);
	
	// 區別2. 對於類的物件,new 會呼叫預設建構函式,而 malloc 只是單純分配空間
	class Car
	{
	public:
		Car(){cout << "Car()" << endl;}
		~Car(){cout << "~Car()" << endl;}
		virtual int p(){cout << "virtual p()" << endl;}
	private:
		int price;
	};

	Car * car_p = (Car *)malloc(sizeof(Car));
	Car * car_q = new Car;

	cout << "sizeof(Car)=" << sizeof(Car) << endl;//應該是 8, 因為一個 int 4 位元組,還有一個虛擬函式表指標 4 位元組

	// 區別3. 對於類的物件,delete 會呼叫解構函式,而 free 只是單純釋放空間
	delete car_q;
	free(car_p);

	// 區別4. 對分配記憶體出現錯誤時,new 會丟擲 bac_alloc 異常, malloc 會返回 NULL
	p = (int *)malloc(INT_MAX);
	if (!p)
		cout << "malloc failed" << endl;
	free(p);
	q = new int[INT_MAX];
	delete []q;
} 

執行截圖