1. 程式人生 > >【C++】記憶體管理方式

【C++】記憶體管理方式

本篇博文旨在介紹C++的記憶體管理方式,並和C語言中的記憶體管理方式作出對比;說明了C語言中的malloc/free和C++中的new/delete的區別;介紹了定位new表示式,來模擬實現new和delete

C中的記憶體管理方式

堆上建立空間

malloc來申請空間,需要自行free進行釋放

除了malloc外,還有calloc,realloc來申請

他們都需要free進行釋放,否則會造成記憶體洩漏

棧上建立空間

編譯器會自己在棧上動態開闢記憶體,利用_alloc來開闢,並自主進行維護

C語言中常見的幾種記憶體洩漏

情況1:忘記了釋放

//去做其他事情了,忘記了釋放
void FunTest1()
{
	int* pTest = (int*)malloc(10 * sizeof(int));
	assert(pTest != NULL);
	//do other thing
	//...忘記了釋放
}

情況2:邏輯出錯

//程式邏輯不清晰,以為釋放了,卻沒有釋放
void FunTest2()
{
	int* pTest1 = (int*)malloc(10 * sizeof(int));
	int* pTest2= (int*)malloc(10 * sizeof(int));
	//do other things
	//...
	pTest1 = pTest2;
	//...
	//do other things

	//記憶體洩漏,現在pTest1和pTest2指向的是同一塊空間
	//原來pTest1申請的空間沒有釋放
	free(pTest1);
	free(pTest2);//錯誤,釋放出錯
}

情況3:申請的空間被錯誤的使用

//程式的錯誤操作,導致了堆的破壞
void FunTest3()
{
	char* pTest = (char*)malloc(sizeof(char)* 5);
	strcpy(pTest,"Memory Leaks");
	free(pTest);//錯誤,申請的記憶體被破壞,釋放出錯
}

情況4:釋放的地址與申請的地址不一致

//釋放時,地址被修改,與申請的地址不一致
void FunTest4()
{
	int* pTest = (int*)malloc(sizeof(int)* 10);
	assert(pTest);
	pTest[0] = 0;
	pTest++;
	//do other things
	free(pTest);//錯誤,釋放出錯
}

C++中的記憶體管理方式


記憶體組織結構

全域性變數、全域性靜態變數、區域性靜態變數、區域性變數儲存位置的區別


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

相同點:

它們都是對記憶體進行管理

區別:

區別1:型別

malloc/free是函式,而new/delete是關鍵字、操作符

區別2:作用

malloc/free只是簡單的進行記憶體的申請和釋放;new/delete除了進行記憶體申請和釋放,還會呼叫物件的建構函式和解構函式進行空間的初始化和清理

區別3:引數與返回值

malloc/free需要手動計算申請記憶體的空間大小,而且返回值是void*,需要自己轉換成所需要的型別;

new/delete可以自己計算型別的大小,返回為對應的型別指標

C++中其他管理記憶體的介面

void* operator new(size_t size);

void operator delete(size_t size);

void* operator new[](size_t size);

void operator delete[](size_t size);

說明:

1、operator new/operator delete  operator new[]/operator delete[] 和malloc/free的使用方法一樣

2、它們只會進行記憶體的申請和釋放,不會呼叫物件的建構函式和解構函式

3、operator new/operator delete 只是對malloc/free的一層封裝

operator new/operator delete operator new[]/operator delete[] 和new/delete 區別

new 的作用

呼叫operator new進行記憶體的事情

呼叫建構函式初始化空間

delete 的作用

呼叫解構函式清理空間

呼叫operator delete釋放空間

new[]的作用

呼叫N次operator new進行記憶體的申請

呼叫建構函式進行初始化

delete[] 的作用

呼叫解構函式對空間進行清理

呼叫N次operator delete釋放空間

定位new表示式

所謂定位new表示式,就是利用malloc/free函式+new表示式/解構函式來模擬new和delete的行為

malloc函式申請空間後,利用定位new表示式顯示呼叫建構函式來模擬new的功能

然後顯示的呼叫析夠函式,最後用free釋放來模擬delete的功能

//定位new表示式
//在用malloc已分配的空間中呼叫建構函式初始化一個物件
class Array
{
public:
	Array(size_t size = 10)
		:_size(size)
		, _a(0)
	{
		cout << "Array()" << endl;
		if (_size > 0)
		{
			_a = new int[_size];
		}
	}
	~Array()
	{
		cout << "~Array()" << endl;
		if (_a)
		{
			delete _a;
			_a = NULL;
			_size = 0;
		}
	}
private:
	int* _a;
	size_t _size;
};

void Test()
{
	//malloc/free+new()/解構函式 模擬new和delete的行為
	
	//模擬new
	Array* p1 = (Array*)malloc(sizeof(Array));
	new(p1)Array(100);

	//模擬delete
	p1->~Array();
	free(p1);

	//模擬new[]
	Array* p2 = (Array*)malloc(sizeof(Array)*10); 
	for (size_t i = 0; i < 10; ++i)
	{
		new(p2 + i)Array;
	}

	//模擬delete[]
	for (size_t i = 0; i < 10; ++i)
	{
		p2[i].~Array();
	}
	free(p2);
}