C/C++語言 淺談C/C++內存管理知識點
首先來展示下內存區域劃分圖
打開今日頭條,查看更多圖片這裡就不介紹堆棧和數據代碼區域了,相信大家都非常熟悉了,簡單談一下內存映射段
內存映射段是高效的I/O映射方式,用於裝載一個共享的動態內存庫。用戶可使用系統介面創建共享共享內存,做進程間通信
這裡提一下大家總是分不清楚的sizeof和strlen
sizeof 和 strlen的區別
sizeof是一個運算符(部分操作時不添加不尾綴括弧),其作用是返回一個對象或者類型在內存中所佔的位元組
strlen是C語言中的庫函數,依賴於<string.h>頭文件,其作用是求字元串的實際長度,方法是從開始直到遇到第一個" "結束
函數原型unsigned int strlen(char* s)
數組做sizeof的參數不退化,傳遞給strlen就退化為指針了
eg:
char* ss = "0123456789";
sizeof(ss); 4
sizeof(*ss); 1
strlen(ss); 10
c語言中動態內存管理方式
malloc
void* malloc(size_t size)
calloc
void* calloc(size_t size, int num)
calloc會將申請的內存大小全部初始化為0
realloc
void* realloc(void* ptr,size_t size)
realloc的功能是將ptr所指向的空間進行調整大小到Size大小的位元組數
如若ptr傳入 的值為null則realloc的功能會和malloc相同
newsize和oldsize對比,如若大不了多少,則返回的地址還為原地址,否則重新分配newsize的內存,進行拷貝操作,然後釋放舊空間
malloc工作原型:https://blog.csdn.net/mmshixing/article/details/51679571
此處需要知道malloc在分配空間時會數據區在之前添加一個meta區記錄數據塊的元信息(數據區大小、空閑標誌位、指針等)
c++語言內存管理方式
先看三個例子的區別
int* ptr1 = new int;
int* ptr2 = new int(10);//動態申請一個int類型的空間並初始化為10
int* ptr3 = new int[10];//動態申請10個int類型的空間
new的原理:
調用operator new(系統全局函數)函數申請空間
在申請的空間上執行構造函數,完成對象的構造
delete的原理:
1.在空間上執行析構函數,完成對象中資源的清理工作
2.調用operator delete(系統全局函數)函數釋放對象的空間
new T[N]的原理:
1.調用operator new[]函數,實際調用operator new函數完成N個對象空間的申請
2.在申請的空間上執行N次構造函數
void* operator new[ ](size_t size = N * sizeof(T) +4)//加4與否取決於T類是否提供析構函數
operator new(size)
delete[]的原理
1.在釋放的對象空間上執行N次析構函數,完成N個對象中資源的a清理(從後往前)
2.調用operator delete[]釋放空間,實際調用operator delete函數完成N個對象空間的申請
在空間內上文提到的4個位元組當中取對象的個數N,調用N次析構函數
void operator delete[ ] (void* p)
operator delete(p)
free(p)
new/delete new[]/delete[] 要成套來使用 否則可能會造成崩潰或者內存泄漏(與析構處理有關)
operator new:該函數實際通過malloc來申請空間,當malloc申請空間成功直接返回,失敗則嘗試執行空間不足的應對措施,如果應對措施用戶設置了,則繼續申請否則拋異常
operator delete:該函數最終是通過free來釋放空間的
operator new( )/operator delete( ) 用戶可以自己實現
返回值必須是void* , 且首參數必然為size_t size
malloc/free & new/delete 區別
1.maollc/free是函數,new/delete是操作符
2.new申請的空間可以初始化,malloc不行
3.malloc的返回值是void*,所以需要計算空間大小並傳遞且使用時必須更改類型,new不需要
4.malloc申請失敗返回NULL,new需要捕獲異常
5.malloc申請的空間一定在堆上,而new不一定,因為operator new可能會存在重載
6.new/delete比malloc/free的效率稍微低點,因為new/delete的底層封裝了maolloc/free
7.malloc/free只能申請內置類型的空間,不能申請自定義類型的空間,因為其不會調用構造與析構函數
這裡普及一個概念,因為我這次總結知識點時第一次看到內置類型這個關鍵詞
內置類型:C++定義餓了一套包括算術類型(字元型,整型,bool型,浮點型)和空類型(函數運行完成之後不返回任何數值)在內的基本數據類型
定位new表達式
定位new表達式是在已分配的原始內存空間中調用構造函數初始化一個對象
void Text()
{
//此時pt指向的只是一個和Test對象有著相同大小的一段空間,因為並沒有實現構造函數
//所以不能說pt就是指向了一個Text對象
Test* pt = (Test*)malloc(sizeof(Test));
//如果Test對象的構造函數需要傳參時這裡應當傳參
new(pt) = Test;
delete pt;
}
怎麼禁止一個函數的拷貝構造函數:
1.在私有里聲明拷貝構造函數(C++98)
2.Test(const Test& t ) = delete
問題:只在堆/棧上創建一個對象?
堆: 私有化聲明拷貝構造和構造函數,提供一個靜態成員函數完成堆上創建對象
棧: 1.屏蔽(私有化)掉new的功能(operator new/delete)
//但全局作用域里還可以創建對象
2.私有化聲明構造函數和拷貝構造,提供一個靜態成員函數創建一個臨時對象返回
//此方法創建了多個臨時對象,資源浪費
創建對象的兩種方式:
1.靜態建立一個類對象,是由編譯器為對象在棧空間中分配內存,是通過直接移動棧頂指針,挪出適當的空間,然後在這片內存空間上調用構造函數形成一個棧對象。使用這種方法,直接調用類的構造函數;
2.動態建立類對象,是使用new運算符將對象建立在堆空間中。這個過程分為兩步,第一步是執行operator new()函數,在堆空間中搜索合適的內存並進行分配;第二步是調用構造函數構造對象,初始化這片內存空間。這種方法,間接調用類的構造函數。
---------------------
作者:李貳一
原文:https://blog.csdn.net/ladykiller21/article/details/86496397
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
※eclipse使用ant + ivy 配置項目jar包和依賴關係
※基於Python Selenium Unittest PO設計模式詳解
TAG:程序員小新人學習 |