最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言的動態(tài)內(nèi)存管理你了解嗎

 更新時間:2022年03月29日 10:43:44   作者:和太陽肩并肩的老楊  
這篇文章主要為大家詳細(xì)介紹了C語言的動態(tài)內(nèi)存管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

C/C++內(nèi)存分配方式

在學(xué)習(xí)C語言階段的時候,創(chuàng)建一個變量,編譯器會為它分配一塊內(nèi)存。而創(chuàng)建一個C++對象的時候,編譯器會為這個對象分配內(nèi)存,并且調(diào)用合適的構(gòu)造函數(shù)進(jìn)行初始化。

那么編譯器的內(nèi)存分配方式是怎樣的呢?

內(nèi)存分配可以有以下的幾種方式

  • 從靜態(tài)存儲區(qū)分配。這樣的分配方式在程序開始前就可以為對象/變量分配,這塊空間在整個程序運行期間都存在。
  • 從棧區(qū)分配。調(diào)用函數(shù)時,函數(shù)的參數(shù),局部變量,返回地址等存儲在堆棧上,函數(shù)執(zhí)行結(jié)束時將會自動釋放這些內(nèi)存空間,棧區(qū)的內(nèi)存空間遠(yuǎn)遠(yuǎn)小于堆區(qū)。
  • 從堆區(qū)分配。這種內(nèi)存分配方式被稱為動態(tài)內(nèi)存分配,堆區(qū)又被稱為“自由存儲單元”,運行時通過調(diào)用相應(yīng)的函數(shù)來申請和釋放內(nèi)存。

有時候我們并不知道程序中的對象確切地需要多少內(nèi)存空間,動態(tài)內(nèi)存分配則很好地處理了這種需求。

C++內(nèi)存管理方式

C庫中提供了函數(shù)malloc,以及它的變種函數(shù)realloc、calloc來動態(tài)地申請內(nèi)存空間。使用函數(shù)free來釋放動態(tài)申請出的內(nèi)存空間。

int* ptr1 = (int*)malloc(sizeof(int));

使用malloc需要指定空間大小,并且要強(qiáng)制類型轉(zhuǎn)化,因為它只是簡單地分配了一塊空間,返回的是void*,而C++中不允許將空類型的指針賦予給其他類型的指針。另外,如果你申請一塊內(nèi)存之后,沒有對這個指針進(jìn)行正確的初始化,有可能會導(dǎo)致程序運行失敗,并且如果忘記釋放動態(tài)申請的內(nèi)存空間,則會造成內(nèi)存泄露等危害……

在創(chuàng)建一個C++對象時,編譯器會做這兩件事:

1.為對象分配內(nèi)存。

2.編譯器自動調(diào)用構(gòu)造函數(shù)初始化該內(nèi)存。

構(gòu)造函數(shù)不支持顯式地調(diào)用,意味著如果使用malloc函數(shù)創(chuàng)建一個對象,那么這個對象將不能夠調(diào)用構(gòu)造函數(shù),僅僅只是開辟了一塊空間。但是我們必須要確保對象被初始化,因為未初始化對象是大部分程序出錯的主要原因??偠灾?,C中的動態(tài)內(nèi)存管理無法滿足C++中動態(tài)對象的需求。

所以提出了newdelete.關(guān)鍵字

new和delete的使用

int main(void)
{
	//基本內(nèi)置類型
	//開辟一個int類型的空間
	int* ptr2 = new int;

	//開辟多個int類型空間
	int* ptr3 = new int[5];

	//開辟一個int類型并初始化為1
	int* ptr4 = new int(1);

	delete ptr2;
	delete[] ptr3;
	delete ptr4;
	return 0;
}

new和delete的使用方式:

1.開辟一個空間: new 類型;       對應(yīng)釋放: delete 對象;2.開辟多個空間:new 類型[個數(shù)]   對應(yīng)釋放:delete[] 對象;3.開辟并初始化: new 類型(初始化數(shù)據(jù)) 對應(yīng)釋放:delete 對象  1.開辟一個空間: new 類型;       對應(yīng)釋放: delete 對象;
2.開辟多個空間:new 類型[個數(shù)]   對應(yīng)釋放:delete[] 對象;
3.開辟并初始化: new 類型(初始化數(shù)據(jù)) 對應(yīng)釋放:delete 對象
  

new和delete的騷操作

內(nèi)置類型

對于內(nèi)置類型,new和delete與C的內(nèi)存管理函數(shù)做了差不多的事情,不同的地方是:new/delete申請和釋放的是單個元素的空間,new[]和delete[]申請的是連續(xù)空間,而且new在申請空間失敗時會拋異常,malloc會返回NULL。

自定義類型

new表達(dá)式:

  • 調(diào)用opreator new函數(shù)分配內(nèi)存
  • 調(diào)用構(gòu)造函數(shù)初始化該內(nèi)存

delete表達(dá)式:

  • 調(diào)用析構(gòu)函數(shù)清理對象中的資源
  • 調(diào)用operator delete釋放空間。

operator new( ) 和operator delete( )這兩個內(nèi)存分配函數(shù)是系統(tǒng)提供的全局函數(shù),實際上是對malloc和free的各種行為進(jìn)行了封裝。

new和delete的區(qū)別

new、delete 和 malloc、free的區(qū)別有哪些呢?

  • new和delete是關(guān)鍵字,malloc和free是函數(shù)
  • malloc申請的空間不會初始化,new會初始化。
  • malloc需要手動計算空間大小并傳遞,new不需要
  • malloc的返回值是void*,使用時必須強(qiáng)制類型轉(zhuǎn)換;new不需要,后面跟的是空間的類型。
  • malloc申請失敗,返回NULL,所以調(diào)用后要判斷是否開辟成功;new需要捕獲異常
  • malloc只是開辟空間,不會調(diào)用構(gòu)造函數(shù),free釋放空間不會調(diào)用析構(gòu)函數(shù);new在申請空間后會調(diào)用構(gòu)造函數(shù)初始化對允許象,delete會調(diào)用析構(gòu)函數(shù)清理對象中的資源,然后再釋放空間。

重載new和delete

C++允許重載new和delete,以實現(xiàn)我們自己的存儲分配方案。但是注意重載operator new和operator delete時,僅僅只能改變原本的內(nèi)存分配方式。同重載其他的運算符一樣,可以分為重載成全局和針對特定類的內(nèi)存分配函數(shù)。

重載全局

重載一個全局的new和delete會導(dǎo)致默認(rèn)版本完全不能被訪問。

重載operator new的要求:

  • 必須有一個size_t參數(shù),該參數(shù)將接收要開辟空間的長度。
  • 返回一個指向?qū)ο蟮闹羔?,該對象的長度等于或者大于所申請的長度。
  • 如果分配失敗,不僅僅要返回一個0,還需產(chǎn)生一個異常信息之類的現(xiàn)象,明確分配內(nèi)存時出了問題。
  • 返回值是一個void*

重載operator delete的要求

  • 參數(shù)是一個指向由operator new()分配的void*類型的內(nèi)存的指針
  • 返回值是void

為什么重載operator delete的時候,參數(shù)是一個void*?

這是因為它是在調(diào)用析構(gòu)函數(shù)后得到的指針。

	//重載operator new
	//1.必須有一個size_t的參數(shù),該參數(shù)將接收要申請開辟空間的大小
	//2.返回值是一個void*
	//3.返回一個指向?qū)ο蟮闹羔槪搶ο蟮拈L度等于或大于所申請的長度
	//4.如果分配失敗。不僅僅要返回一個0,還需產(chǎn)生一個異常信息
	void* operator new(size_t sz)
	{
		cout << "new %d Bytes" << sz << endl;
		void* p = nullptr;
		//不需要強(qiáng)制類型轉(zhuǎn)換,因為malloc返回的就是void*
		p = malloc(sz);
		if (nullptr == p)
		{
			cout << "new fail\n" << endl;
		}
		return p;
	}
	//重載operator delete
	//1.返回值為void
	//2.參數(shù)是一個指向由operator new()返回的void*的指針
	void operator delete(void* rp)
	{
		cout << "operator delete" << endl;
		free(rp);
	}

重載類專屬

//重載ListNode專屬的operator new
struct ListNode
{
	ListNode* _next;
	ListNode* _prev;
	int _data;
	void* operator new(size_t n)
	{
		void* p = nullptr;
		p = allocator<ListNode>().allocate(1);
		cout << "memory pool allocate" << endl;
		return p;
	}
	void operator delete(void* p)
	{
		allocator<ListNode>().deallocate((ListNode*)p, 1); //內(nèi)存池--空間適配器
		cout << "memory pool deallocate" << endl;
	}
};
class List
{
public:
	List()
	{
		_head = new ListNode;
		_head->_next = _head;
		_head->_prev = _head;
	}
	~List()
	{
		ListNode* cur = _head->_next;
		while (cur != _head)
		{
			ListNode* next = cur->_next;
			delete cur;
			cur = next;
		}
		delete _head;
		_head = nullptr;
	}
private:
	ListNode* _head;
};
int main()
{
	List l;
	return 0;
}

定位new表達(dá)式

定位new表達(dá)式:它的作用是在已分配的原始內(nèi)存空間中用構(gòu)造函數(shù)初始化一個對象

使用的格式:

new (place_address) type 或者 new (place_address) type (initializer-lost) place_address必須是一個指針,initializer-list是初始化列表。

//例如
class Test
{
public:
	Test()
		: _data(0)
	{
		cout << "Test():" << this << endl;
	}
	~Test()
	{
		cout << "~Test():" << this << endl;
	}

private:
	int _data;
};

int main(void)
{
	// pt現(xiàn)在指向的只不過是與Test對象相同大小的一段空間,還不能算是一個對象,因為構(gòu)造函數(shù)沒有執(zhí)行
	Test* pt = (Test*)malloc(sizeof(Test));

	//定位new
	new(pt) Test; // 注意:如果Test類的構(gòu)造函數(shù)有參數(shù)時,此處需要傳參
	return 0;
}

內(nèi)存泄露

內(nèi)存泄露的含義:

內(nèi)存泄漏指因為疏忽或錯誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并不是指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,因為設(shè)計錯誤,失去了對該段內(nèi)存的控制,因而造成了內(nèi)存的浪費。

內(nèi)存泄露的兩大分類:

1.堆內(nèi)存泄露(Heap leak)

堆內(nèi)存指的是程序執(zhí)行中依據(jù)須要分配通過malloc / calloc / realloc / new等從堆中分配的一塊內(nèi)存,用完后必須通過調(diào)用相應(yīng)的 free或delete 刪掉。假設(shè)程序的設(shè)計錯誤導(dǎo)致這部分內(nèi)存沒有被釋放,那么以后這部分空間將無法再被使用,就會產(chǎn)生Heap Leak。

2.系統(tǒng)資源泄露

指程序使用系統(tǒng)分配的資源,比方套接字、文件描述符、管道等沒有使用對應(yīng)的函數(shù)釋放掉,導(dǎo)致系統(tǒng)資源的浪費,嚴(yán)重可導(dǎo)致系統(tǒng)效能減少,系統(tǒng)執(zhí)行不穩(wěn)定。

內(nèi)存泄露的危害:

在平時寫一些小測試的時候,并沒有覺得內(nèi)存泄露的危害特別大,但是在長期運行的程序中出現(xiàn)內(nèi)存泄漏,影響非常的大,出現(xiàn)內(nèi)存泄露可能會導(dǎo)致響應(yīng)越來越慢,最終出現(xiàn)卡死的現(xiàn)象。

內(nèi)存泄露的解決方案分兩種:

1.事先預(yù)防 。

2. 事后查錯

如何事先預(yù)防?

1.養(yǎng)成良好的編碼習(xí)慣,申請了內(nèi)存要記得釋放。

2.采用RAII思想或者智能指針來管理資源。

3.規(guī)范使用內(nèi)部實現(xiàn)的私有內(nèi)存管理庫。

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • c語言 sscanf,scanf,fscanf正則表達(dá)式用法

    c語言 sscanf,scanf,fscanf正則表達(dá)式用法

    每種語言都對正則表達(dá)式有著不同程度的支持,在C語言中,有輸入功能的這三個函數(shù)對正則表達(dá)式的支持并不強(qiáng)大,但是我們還是有必要了解一下
    2018-04-04
  • c++11中regex正則表達(dá)式示例簡述

    c++11中regex正則表達(dá)式示例簡述

    這篇文章主要給大家介紹了關(guān)于c++11中regex正則表達(dá)式的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用c++11具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • C++遞歸實現(xiàn)螺旋數(shù)組的實例代碼

    C++遞歸實現(xiàn)螺旋數(shù)組的實例代碼

    這篇文章主要介紹了C++遞歸實現(xiàn)螺旋數(shù)組的實例代碼,代碼簡單易懂,非常不錯,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • C++模板元編程實現(xiàn)選擇排序

    C++模板元編程實現(xiàn)選擇排序

    這篇文章主要介紹了C++模板元編程實現(xiàn)選擇排序,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • C語言和go語言之間的交互操作方法

    C語言和go語言之間的交互操作方法

    下面小編就為大家?guī)硪黄狢語言和go語言之間的交互操作方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • C語言中一些將字符串轉(zhuǎn)換為數(shù)字的函數(shù)小結(jié)

    C語言中一些將字符串轉(zhuǎn)換為數(shù)字的函數(shù)小結(jié)

    這篇文章主要介紹了C語言中一些將字符串轉(zhuǎn)換為數(shù)字的函數(shù)小結(jié),分別為atoi()函數(shù)和atol()函數(shù)以及atof()函數(shù),需要的朋友可以參考下
    2015-08-08
  • C語言中.與->的用法介紹

    C語言中.與->的用法介紹

    結(jié)構(gòu)體用點,結(jié)構(gòu)體指針用箭頭,簡單的說,就是一個快捷方式,一個語法糖,這篇文章主要介紹了C語言中.與->的區(qū)別及用法,需要的朋友可以參考下
    2023-05-05
  • C/C++實現(xiàn)發(fā)送與接收HTTP/S請求的示例代碼

    C/C++實現(xiàn)發(fā)送與接收HTTP/S請求的示例代碼

    HTTP(Hypertext Transfer Protocol)是一種用于傳輸超文本的協(xié)議,它是一種無狀態(tài)的、應(yīng)用層的協(xié)議,用于在計算機(jī)之間傳輸超文本文檔,通常在 Web 瀏覽器和 Web 服務(wù)器之間進(jìn)行數(shù)據(jù)通信,本文給大家介紹了C/C++發(fā)送與接收HTTP/S請求,需要的朋友可以參考下
    2023-11-11
  • C++利用隨機(jī)策略實現(xiàn)優(yōu)化二叉樹操作效率

    C++利用隨機(jī)策略實現(xiàn)優(yōu)化二叉樹操作效率

    這篇文章中我們主要來詳細(xì)探討隨機(jī)化二叉搜索樹的基本思想、實現(xiàn)方法,以及如何在C++中應(yīng)用這些策略來優(yōu)化我們的數(shù)據(jù)結(jié)構(gòu),感興趣的可以了解下
    2024-02-02
  • C++中const修飾符的詳解及其作用介紹

    C++中const修飾符的詳解及其作用介紹

    這篇文章主要介紹了C++中const修飾符的詳解及其作用介紹,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09

最新評論

漯河市| 肥城市| 沂源县| 乌审旗| 金川县| 普安县| 高碑店市| 遂川县| 岐山县| 阿鲁科尔沁旗| 迭部县| 广汉市| 绥阳县| 陇西县| 茂名市| 绵阳市| 哈尔滨市| 安仁县| 鞍山市| 西贡区| 阿勒泰市| 长泰县| 夏河县| 当阳市| 泊头市| 佛学| 乌拉特前旗| 扎赉特旗| 景泰县| 霍山县| 吉木乃县| 剑河县| 济南市| 阿克苏市| 乌鲁木齐市| 渭源县| 正镶白旗| 东源县| 常山县| 汤原县| 天门市|