當前位置:
首頁 > 知識 > C/C++語言 淺談C/C++內存管理知識點

C/C++語言 淺談C/C++內存管理知識點

首先來展示下內存區域劃分圖

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:程序員小新人學習 |