【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);
}