c++动态内存管理
c/c++內存分布
虛擬地址空間分布
為什么操作系統要劃分這些區段
答:為了找數據,存數據方便
以下的代碼分別在虛擬地址空間中的哪個段
int globalVar = 1; //數據段static int staticGlobalVar = 1; //數據段void Test() { static int staticVar = 1; //數據端int localVar = 1; //棧int num1[10] = {1, 2, 3, 4}; //棧char char2[] = "abcd"; //char數組在棧,里面存儲的abcd字符串常量在代碼段char* pChar3 = "abcd"; //pChar指針在棧上,里面的abcd字符串常量在代碼段int* ptr1 = (int*)malloc(sizeof (int)*4); //指針在棧上,分配的空間在堆上int* ptr2 = (int*)calloc(4, sizeof(int)); //指針在棧上,分配的空間在堆上int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4); //指針在棧上,分配的空間在堆上free (ptr1); free (ptr3);}sizeof與strlen的區別
c語言動態開辟空間
動態申請空間的方式
相同點:
- 都是從堆上開辟空間
- 返回值類型都是void*
- 申請空間失敗,返回的都是NULL
- 申請的空間都需要手動釋放
- 在接收返回值時都需要進行強制類型轉換
不同點
malloc:
- 參數:字節數,
- 不會對申請的空間進行初始化,
- 在接收返回值時必須強制類型轉換
- 如果申請空間失敗,返回值NULL,使用前必須判斷是否為空
calloc:
- 參數列表不同:void * calloc ( size_t num, size_t size );,第一個為元素個數,第二個為單個元素大小
- 函數功能差異:calloc會將申請的空間初始化為0
realloc
- 參數列表:void * realloc ( void * ptr, size_t size );
- 函數功能:將ptr所指向的空間調整到size字節,如果ptr為空----->函數行為與malloc相同
- ptr非空,判斷是縮小還是增大,縮小的話,對原空間進行調整,最后返回該空間的首地址,擴大的話,有兩種情況:1. 擴大一點,2.擴大很多
動態釋放方式
手動free
malloc
int* p =(int*)malloc(10*sizeof(int));40字節-----堆上,只要把空間分配給一個應用程序,那么其他應用程序就用不了。系統必須對malloc申請的空間進行管理。
一般malloc申請空間時,比如申請40個字節,除了申請的40字節空間,他還會在前面加一個結構體來管理40字節的空間,在后面加4個字節的空間用來防止越界
詳解c中動態內存分配
C++內存管理方式
C語言內存管理方式在C++中可以繼續使用,但有些地方就無能為力而且使用起來比較麻煩,因此C++又提出 了自己的內存管理方式:通過new和delete操作符進行動態內存管理。
new申請內置類型
int main() {//new 申請單個類型元素的空間----默認情況下new出的空間在堆上int *p1 = new int;int *p2 = new int(10);int *p3 = new int[10];int *p4 = new int[10]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0};delete p1;delete p2;delete[] p3;delete[] p4;return 0; }注意:申請和釋放單個元素的空間,使用new和delete操作符,申請和釋放連續的空間,使用new[]和 delete[]
如果沒有匹配
如果申請的是內置類型的空間,沒有匹配的話,不會產生任何后果
void Test() {int *p1 = (int *)malloc(sizeof(int)* 4);int *p2 = (int *)malloc(sizeof(int)* 4);delete p1;delete p2;int *p3 = new int;int *p4 = new int;free(p3);delete[]p4;int *p5 = new int[10];int *p6 = new int[10];free(p5);delete p6; }new申請自定義類型數據
未進行匹配使用
//自定義類型 class Test { public:Test(){_data = 10;cout << "Test():" << this <<endl;}~Test(){cout << "~Test()" << this << endl;} private:int _data;};void Test2() {Test *p1 = (Test *)malloc(sizeof(Test)* 4);//Test *p2 = (Test *)malloc(sizeof(Test)* 4);delete p1;//delete[] p2;Test *p3 = new Test;Test *p4 = new Test;free(p3);delete[]p4;Test *p5 = new Test[10];Test *p6 = new Test[10];free(p5);delete p6; }operator new與operator delete函數
new是先調用構造函數,還是先申請空間?
第一件事情:申請內存空間,第二才是調用構造函數,完成對象的初始化
new和delete是用戶進行動態內存申請和釋放的操作符,operator new 和operator delete是系統提供的 全局函數,new在底層調用operator new全局函數來申請空間,delete在底層通過operator delete全局 函數來釋放空間。
循環調用malloc來不斷申請空間,直到申請成功,
delete p;
總結
operator new 實際也是通過malloc來申請空間,如果malloc申請空間 成功就直接返回,否則執行用戶提供的空間不足應對措施,如果用戶提供該措施就繼續申請,否則就拋異 常。operator delete 最終是通過free來釋放空間的
void* operator new(size_t size,const char* file,const char* funname,size_t line) {cout << file << "-" << funname << "-" << line << "-" << size << endl;return malloc(size); }void operator delete(void *p, const char* file, const char* funname, size_t line) {cout << file << "-" << funname << "-" << line << "-" << endl;free(p); } #define new new(__FILE__, __FUNCDNAME__, __LINE__)int main() {int *p = new int;delete p;system("pause");return 0; }new和delete的實現原理
內置類型
如果申請的是內置類型的空間,new和malloc,delete和free基本類似,不同的地方是:new/delete申請和 釋放的是單個元素的空間,new[]和delete[]申請的是連續空間,而且new在申請空間失敗時會拋異常, malloc會返回NULL
自定義類型
- new的原理
- 調用operator new函數申請空間
- 在申請的空間上執行構造函數,完成對象的構造
- delete的原理
- 在空間上執行析構函數,完成對象中資源的清理工作
- 調用operator delete函數釋放對象的空間
- new T[N]的原理
- 調用operator new[]函數,在operator new[]中實際調用operator new函數完成N個對象空間的申 請
- 在申請的空間上執行N次構造函數
- delete[]的原理
- 在釋放的對象空間上執行N次析構函數,完成N個對象中資源的清理
- 調用operator delete[]釋放空間,實際在operator delete[]中調用operator delete來釋放空間
內存碎片化
如果每回一小塊一小塊申請內存,就會造成內存的浪費。所以c++有一個現成的內存池就是空間配置器
以下代碼對鏈表的節點ListNode通過重載類專屬 operator new/ operator delete,實現鏈表節 點使用內存池申請和釋放內存,提高效率。
定位new表達式
在已經存在的空間上執行構造函數
使用格式:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必須是一個指針,initializer-list是類型的初始化列表
使用場景:
定位new表達式在實際中一般是配合內存池使用。因為內存池分配出的內存沒有初始化,所以如果是自定義類型的對象,需要使用new的定義表達式進行顯示調構造函數進行初始化
關于c++動態管理方面的題目
題目總結的鏈接
總結
- 上一篇: 大力女都奉顺剧情介绍
- 下一篇: 剑网1归来五行激活有什么用