文章目錄
- 一、C/C++中的內存劃分
- 二、C語言中動態內存管理方式
- 三、C++中動態內存管理方式
- 1、new、delete基本用法
- (1)、內置類型
- (2)、自定義類型
- 2、operator new與operator delete函數
- 3、new和delete的實現原理
- (1)內置類型
- (2)自定義類型
- 4、malloc/free和new/delete的區別
- 四、謝謝觀看!
一、C/C++中的內存劃分
- 棧又叫堆棧----存儲非靜態局部變量、函數參數、返回值等,棧是向下增長的。
- 內存映射段是高效的I/O映射方式,用于裝載一個共享的動態內存庫。用戶可以使用系統接口創建共享內存,做進程間通信。
- 堆----用于程序運行時動態內存分配,堆是向上增長的。
- 數據段(靜態區)----存儲全局數據和靜態數據。
- 代碼段(常量區)----存儲可執行的代碼、只讀常量。
題目練習:
如以上代碼,問:
選擇題:
選項 : A.棧 B.堆 C.數據段(靜態區) D.代碼段(常量區)
globalVar在哪里?____
staticGlobalVar在哪里?____
staticVar在哪里?____
localVar在哪里?____
num1 在哪里?____
char2在哪里?____
*char2在哪里?___
pChar3在哪里?____
*pChar3在哪里?____
ptr1在哪里?____
*ptr1在哪里?____
答案:CCCAA AAADAB
講解:
二、C語言中動態內存管理方式
malloc / calloc /realloc /free
這里就不在講解用法了。
三、C++中動態內存管理方式
關鍵字 : new 、delete
C++通過new來動態申請內存,通過delete來釋放內存。簡化了C語言中malloc的使用。
1、new、delete基本用法
(1)、內置類型
int* p1 = new int;//開辟一個int類型的空間給p1
int* p2 = new int[10];//開辟10個int類型的空間給p2delete p1;//釋放P1
delete[] p2;//釋放p2//C++支持申請對象+初始化
//單個對象初始化
int* p3 = new int(0);//p3指向被初始化為0的變量
//多個對象初始化
int* p4 = new int[10]{0};
int* p5 = new int[10]{1,2,3,4,5};//初始化部分對象
delete p3;
delete[] p4;
delete[] p5;
(2)、自定義類型
#include<iostream>
using namespace std;class A
{
public:A(int a1 = 0, int a2 = 0):_a1(a1), _a2(a2){cout << "A(int a1 = 0, int a2 = 0)" << endl;}~A(){cout << "~A()" << endl;}private:int _a1;int _a2;
};
int main()
{A* p1 = new A();A* p2 = new A();delete p1;delete p2;return 0;
}
new調用類的構造函數,delete調用類的析構函數。
之前我們用C語言來構建鏈表時,對每個節點都要進行malloc來開辟空間,并且進行初始化賦值,有了new之后,就方便了很多:
struct ListNode
{int val;ListNode* next;ListNode(int a):val(a), next(nullptr){}
};
int main()
{ListNode* n1 = new ListNode(1);ListNode* n2 = new ListNode(2);ListNode* n3 = new ListNode(3);ListNode* n4 = new ListNode(4);n1->next = n2;n2->next = n3;n3->next = n4;return 0;
}
#include<iostream>
using namespace std;class A
{
public:默認構造//A(int a1 = 0, int a2 = 0)// :_a1(a1)// , _a2(a2)//{// cout << "A(int a1 = 0, int a2 = 0)" << endl;//}//構造函數A(int a1 , int a2 ):_a1(a1), _a2(a2){cout << "A(int a1 = 0, int a2 = 0)" << endl;}~A(){cout << "~A()" << endl;}private:int _a1;int _a2;
};
int main()
{A* p1 = new A();//在有默認構造函數時:A* p2 = new A[3];//會調用三次構造函數//在沒有默認構造函數時:對其進行初始化//方法1(拷貝構造)A aa1(1,1);A aa2(2,2);A aa3(3,3);A* p3 = new A[3]{aa1,aa2,aa3};//方法2(匿名對象)A* p4 = new A[3]{A(1,1),A(2,2),A(3,3)}//匿名對象//方法3(隱式類型轉換)A* p5 = new A[3]{ {1,1},{2,2},{3,3} };delete p1;delete[] p2;return 0;
}
2、operator new與operator delete函數
new和delete是用戶進行動態內存申請和釋放的操作符,operator new和operator delete是系統提供的全局函數,new在底層調用operator new全局函數來申請空間,delete在底層通過operator delete全局函數來釋放空間。
operator new 實際也是通過maloc來申請空間,如果malloc申請空間成功就直接返回,否則執行用戶提供的空間不足應對措施,如果用戶提供該措施就繼續申請,否則就拋異常。operator delete 最終是通過free來釋放空間的。
3、new和delete的實現原理
(1)內置類型
如果申請的是內置類型的空間,new和malloc,delete和free基本類似,不同的地方是: new/delete申請和釋放的是單個元素的空間,new[]和delete[]申請和釋放的是連續空間,而且new在申請空間失敗時會拋異常,malloc會返回NULL。
(2)自定義類型
(1)new原理
1.調用operator new函數申請空間
2.在申請的空間上執行構造函數,完成對象的構造
(2)delete原理
- 在空間上執行析構函數,完成對象中資源的清理工作
- 調用operator delete函數釋放對象的空間
(3)new T[N]原理
- 調用operator new[]函數,在operator new[]中實際調用operator new函數完成N個對
象空間的申請- 在申請的空間上執行N次構造函數
(4)delete[]原理
- 在釋放的對象空間上執行N次析構函數,完成N個對象中資源的清理
- 調用operator delete[]釋放空間,實際在operator delete[]中調用operator delete來釋
放空間
4、malloc/free和new/delete的區別
malloc/free和new/delete的共同點是:都是從堆上申請空間,并且需要用戶手動釋放。
不同點:
1.malloc和free是函數,new和delete是操作符
2.malloc申請的空間不會初始化,new可以初始化
3.malloc申請空間時,需要手動計算空間大小并傳遞,new只需在其后跟上空間的類型即可如果是多個對象,[]中指定對象個數即可
4. malloc的返回值為void*,在使用時必須強轉,new不需要,因為new后跟的是空間的類型
5.malloc申請空間失敗時,返回的是NULL,因此使用時必須判空,new不需要,但是new需要捕獲異常
6.申請自定義類型對象時,malloc/free只會開辟空間,不會調用構造函數與析構函數,而new在申請空間后會調用構造函數完成對象的初始化,delete在釋放空間前會調用析構函數完成空間中資源的清理釋放