1.c語言動態內存管理
c語言使用malloc、calloc、realloc、free進行動態內存管理
Void test()
{
int* p1 = (int*)malloc(size(int)*4);
int* p2 = (int*)calloc(4,sizeof(int));
int* p3 = (int*)realloc(p2,sizeof(int)*6);
free(p1);
free(p2);
free(p3);
}
(1)malloc函數在內存的動態存儲區中分配一塊長度爲size字節的連續區域,返回該區域的地址,不初始化。
(2)calloc函數與malloc函數相似,不同的是calloc會將所分配的空間中的每一位都初始化爲零。
(3)realloc函數會首先判斷oldbase後是否有足夠要求的新空間,若有,則擴大oldbase指向的地址空間;若沒有,就重新另外分配一塊地址空間,並將原有的數據拷貝到新的空間,然後釋放原有的內存空間,同時返回新分配的內存空間首地址。
malloc、calloc、realloc必須和free匹配使用,否則可能出現內存泄露甚至崩潰的問題。
2.c++是兼容c的,而c語言庫中已經有malloc/free等管理動態內存,爲什麼c++還要定義new/delete運算符來管理動態內存呢?
malloc/free和new/delete的區別與聯繫
(1)它們都是動態管理內存的入口;
(2)malloc/free是c/c++庫中函數,new/delete是c++中的操作符;
(3)malloc/free只是動態分配內存空間/釋放空間,而new/delete不僅分配空間還調用構造函數和析構函數進行初始化和清理(清理成員);
(4)malloc/free需要手動計算類型大小且返回值爲void*,new/delete可自動計算類型大小且返回的是對應類型的指針。
因此引入c++動態內存管理new/delete操作符。
3.c++動態內存管理基本語法和使用
new/delete動態管理對象
new[]/delete[]動態管理對象數組
void test()
{
int* p1 = new int;//動態分配4個字節(1個int)的空間單個數據
int* p2 = new int(3);//動態分配4個字節(1個int)的空間並初始化爲3
int* p3 = new int[3];//動態分配12個字節(3個int)的空間
delete p1;
delete p2;
delete [] p3;
}
new/delete和new[]/delete[]必須匹配使用,否則可能出現內存泄露甚至崩潰的問題。
(1)new/operator底層實現
#include<iostream>
//#include<cstdlib>
using namespace std;
class Array
{
public:
Array(size_t size = 5)
:_size(size)
, _a(0)
{
cout << "Array(size_t size)" << endl;
if (_size > 0)
{
_a = new int[size];
}
}
~Array()
{
cout << "~Array()" << endl;
if (_a)
{
delete[] _a;
_a = 0;
_size = 0;
}
}
private:
int* _a;
size_t _size;
};
void Test()
{
Array* p1 = (Array*)malloc(sizeof(Array));
Array* p2 =new Array;
Array* p3 =new Array(20);
Array* p4 =new Array[10];
free(p1);
delete p2;
delete p3;
delete[] p4;
}
int main()
{
Test();
system("pause");
return 0;
}
調試轉到反彙編可以看到,new調用了operator new開闢空間
然後調用構造函數初始化
delete、delete[]調用析構函數清理對象,然後調用operator delete、operator delete[]釋放空間。
(2)void* operator new (size_t size);
void operator new (void* p);
void* operator new (size_t size);
void operator new (void* p);
operator new/operator delete,operator new[]/operator delete[]和malloc/free用法一樣。
他們只負責分配空間/釋放空間,不會調用對象構造函數/析構函數來初始化/清理對象。
實際operator new和operator delete只是malloc和free的一層封裝。
注意:
operator new()/operator delete()是c++的標準庫函數,而不是運算符的重載。
(3)new[N]
*.調用operator new分配空間;
*.調用N次構造函數分別初始化每個對象。
Delete[]
*.調用N次析構函數清理對象;(思考N是如何而來?)
*.調用operator delete釋放空間。
根據以上代碼中的
Array* p4 =new Array[10];
delete[] p4;
得 這兩條語句實際是調用operator new[](10*sizeof(Array)+4)分配大小爲10*sizeof(Array)+4空間,其中多的四個字節空間用於存放delete中調用析構函數的次數,空間申請好後調用構造函數創建對象。
delete[] p4執行時首先取N個對象個數,然後調用析構函數析構對象,最後用operator delete[]函數釋放空間。
總結:new在開闢內置類型空間時,開闢的空間數量是指定的空間數量,字節數是指定的數量乘以類型的大小;當爲非內置類型開闢空間,並且該類有自定義的析構函數時,纔會多出4個字節。
(4)定位new表達式
在已分配的原始內存空間中的特定位置處調用構造函數初始化一個對象。
模擬實現new表達式
模擬實現DELETE