亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++圖文并茂分析講解內(nèi)存管理

 更新時(shí)間:2022年09月15日 15:48:55   作者:龜龜不斷向前  
本章主要介紹C語(yǔ)言與C++的內(nèi)存管理,以C++的內(nèi)存分布作為引入,介紹C++不同于C語(yǔ)言的內(nèi)存管理方式(new delete對(duì)比 malloc free),感興趣的朋友來(lái)看看吧

1.了解一些基本的內(nèi)存段(圖演示)

驗(yàn)證棧是向下生長(zhǎng)的

#include<iostream>
using namespace std;
int main()
{
	int a = 3;
	int b = 4;
	int c = 5;
	int d = 6;
	cout <<"a:"<< &a << endl;
	cout << "b:"<<&b << endl;
	cout << "c:"<<&c << endl;
	cout << "d:"<<&d << endl;
	return 0;
}

驗(yàn)證堆一般是向上生長(zhǎng)的(不一定)

#include<iostream>
using namespace std;
int main()
{
	int num = 10;
	while (num--)
	{
		int *p1 = (int*)malloc(sizeof(int));
		int *p2 = (int*)malloc(sizeof(int));
		cout <<"p1"<< p1 << endl;
		cout <<"p2"<<p2 << endl;
		cout << endl;
		free(p1);
	}
	return 0;
}

一般情況下,p1的地址是比p2的地址高的(因?yàn)槎岩话闶窍蛏仙L(zhǎng)的),但是有時(shí)候是不一定的。

鞏固內(nèi)存管理知識(shí)點(diǎn)

答案

溫馨提示:題目中的指針是局部指針變量,是在棧上的,但是它指向的內(nèi)容(解引用)可能是堆區(qū)或者常量區(qū)的。,可以畫(huà)畫(huà)圖理解理解

2.c++申請(qǐng)動(dòng)態(tài)內(nèi)存的新玩兒法new,delete

回顧c語(yǔ)言動(dòng)態(tài)內(nèi)存管理的方式

malloccallocrealloc

  • malloc堆上動(dòng)態(tài)開(kāi)空間
  • calloc堆上動(dòng)態(tài)開(kāi)空間+初始化成0等價(jià)于malloc+memset
  • realloc指針已有的空間擴(kuò)容

原題增容–后面又足夠的空間

異地增容–后面沒(méi)有足夠的空間

開(kāi)辟內(nèi)置類型的空間

//C++開(kāi)辟動(dòng)態(tài)內(nèi)存的新玩法
//語(yǔ)法演示:
#include<iostream>
using namespace std;
int main()
{
	//申請(qǐng)一個(gè)int的動(dòng)態(tài)空間
	int* p1 = (int*)malloc(sizeof(int));
	*p1 = 1;
	int* p2 = new int(2);//這里是初始化
	free(p1);
	delete p2;
	//申請(qǐng)一個(gè)10各int的動(dòng)態(tài)數(shù)組
	int *p3 = (int*)malloc(sizeof(int)* 10);
	for (int i = 0; i < 10; i++)
	{
		p3[i] = i + 1;
	}
	int *p4 = new int[10]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//初始化
	free(p3);
	delete[]p4;
	return 0;
}

跟c語(yǔ)言的版本相比,c++的版本,初始化時(shí)顯得比較方便,而且語(yǔ)法比較簡(jiǎn)潔。當(dāng)然了,更大的優(yōu)越性還在后面。

開(kāi)辟自定義類型的空間(請(qǐng)用vs2013以上版本測(cè)試代碼)

#include<iostream>
using namespace std;
struct ListNode
{
	int _val;
	ListNode* _next;
	ListNode* _prev;
	//構(gòu)造函數(shù)
	ListNode(int val = 0)
	:_val(val)
	, _next(nullptr)
	, _prev(nullptr)
	{
        cout<<"ListNode(int val = 0)"<<endl;
    }
	~ListNode()
	{
		cout << "ListNode()" << endl;
	}
};
int main()
{
	//申請(qǐng)一個(gè)結(jié)點(diǎn)的空間
    ListNode* pa = (ListNode*)malloc(sizeof(ListNode)*4);
	ListNode* pb = new ListNode(1);//不用去用sizeof去計(jì)算空間大小,很方便   
	free(pa);
	delete pb;
	//申請(qǐng)4個(gè)結(jié)點(diǎn)的空間--當(dāng)然了一般不會(huì)這么玩兒,我們只是看看效果
	ListNode* pc = (ListNode*)malloc(sizeof(ListNode)* 4);
	ListNode* pd = new ListNode[4]{1, 2, 3, 4};
	free(pc);
	delete[]pd;
	return 0;
}

? 學(xué)過(guò)c語(yǔ)言版本的數(shù)據(jù)結(jié)構(gòu)的小伙伴都知道,我們push_back一個(gè)結(jié)點(diǎn)時(shí),需要先實(shí)現(xiàn)一個(gè)buynewnode的函數(shù)(創(chuàng)建一個(gè)結(jié)點(diǎn),并且對(duì)其進(jìn)行初始化)。而new這個(gè)操作符,在創(chuàng)建結(jié)點(diǎn)的同時(shí),已經(jīng)幫我們實(shí)現(xiàn)了結(jié)點(diǎn)的初始化。調(diào)用了構(gòu)造函數(shù),而且delete還調(diào)用了析構(gòu)函數(shù)。

總結(jié)一下

  1. c++中,如果是申請(qǐng)內(nèi)置類型對(duì)象或者數(shù)組,mallocnew沒(méi)有太大區(qū)別
  2. 如果時(shí)自定義類型,區(qū)別很大,new和delete時(shí)開(kāi)空間+初始化,析構(gòu)清理+釋放空間,mallocfree僅僅時(shí)開(kāi)空間+釋放空間
  3. 建議在c++中,無(wú)論時(shí)內(nèi)置類型還是自定義類型的申請(qǐng)釋放,盡量使用new和delete。

3. 32位平臺(tái)下可以開(kāi)辟多大的內(nèi)存

我:cpu過(guò)來(lái)遭罪

cpu:你不要過(guò)來(lái)啊

上述程序,我們開(kāi)了1.8 G左右的內(nèi)存,加上需要堆上的小內(nèi)存,最后的綜合有2 G的空間

如何開(kāi)辟4G的內(nèi)存

將項(xiàng)目屬性修改一下,改成64位平臺(tái)即可,64位平臺(tái)有2^34 G的空間(虛擬內(nèi)存)在這我們不做細(xì)說(shuō),因?yàn)槲乙膊惶私釲inux。

4.了解operator new和operator delete

new其實(shí)是operator new + 構(gòu)造函數(shù)

delete其實(shí)是operator delete+構(gòu)造函數(shù)

newdelete是用戶進(jìn)行動(dòng)態(tài)內(nèi)存申請(qǐng)和釋放的操作符,operator newoperator delete是系統(tǒng)提供的全局函數(shù),new在底層調(diào)用operator new全局函數(shù)來(lái)申請(qǐng)空間,delete在底層通過(guò)operator delete全局函數(shù)來(lái)釋放空間

大家可以將operator new和operator delete理解成和malloc 和free一樣用法的函數(shù)。

唯一不同的地方是,operator new和malloc開(kāi)辟空間失敗的處理方式不一樣,malloc是返回NULL空指針,而operator是拋異常,下面代碼讓大家看看效果,不必深究,以后會(huì)有介紹。

struct ListNode
{
	int _val;
	ListNode* _next;
	ListNode* _prev;
	//構(gòu)造函數(shù)
	ListNode(int val = 0)
		:_val(val)
		, _next(nullptr)
		, _prev(nullptr)
	{
		cout << "ListNode(int val = 0)" << endl;
	}
	~ListNode()
	{
		cout << "ListNode()" << endl;
	}
};
void f()
{
	// 他的用法跟malloc和free是完全一樣的,功能都是在堆上申請(qǐng)釋放空間
	// 失敗了處理方式不一樣,malloc失敗返回NULL,operator new失敗以后拋異常
	ListNode* p1 = (ListNode*)malloc(sizeof(ListNode));
	free(p1);
	ListNode* p2 = (ListNode*)operator new(sizeof(ListNode));
	operator delete(p2);
	void* p3 = malloc(0x7fffffff);
	if (p3 == NULL)
	{
		cout << "malloc fail" << endl;
	}
	void* p4 = operator new(0x7fffffff);
	ListNode* p5 = new ListNode(2);
	cout << "繼續(xù)" << endl;
}
//
//
int main()
{
	try
	{
		f();
	}
	catch (exception& e)
	{
		cout << e.what() << endl;
	}
	return 0;
}

malloc失敗返回NULL,程序還會(huì)繼續(xù)向下執(zhí)行,但是operator new失敗,就會(huì)報(bào)異常,f函數(shù)后面的沒(méi)有在繼續(xù)執(zhí)行,然后走進(jìn)catch語(yǔ)句中。

5.operator new和operator delete的類函數(shù)重載

struct ListNode//目的是提高效率
{
	ListNode* _next;
	ListNode* _prev;
	int _val;
	// 類中重載專屬operator new
	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);
		cout << "memory pool deallocate" << endl;
	}
	ListNode(int val)
		:_next(nullptr)
		, _prev(nullptr)
		, _val(val)
	{}
};
int main()
{
	ListNode* p = new ListNode(1);
	delete p;
	return 0;
}

如果你自己在類里面寫(xiě)了operator newoperator delete,那么編譯器就不會(huì)去調(diào)用系統(tǒng)提供的了,這是一種提高效率的方式。

我們是可以通過(guò)反匯編來(lái)看效果的

6.定位new–placement-new

通過(guò)上述的學(xué)習(xí)我們知道,malloc,和operator是不會(huì)去調(diào)用構(gòu)造函數(shù)的,new會(huì)去調(diào)用構(gòu)造函數(shù),而且構(gòu)造函數(shù)是只允許構(gòu)造出對(duì)象時(shí)調(diào)用,而你的對(duì)象創(chuàng)建出來(lái)之后是無(wú)法調(diào)用構(gòu)造的。

但是如果我們operator new了一塊空間(未初始化),但是又想要調(diào)用其構(gòu)造函數(shù),該怎們辦呢?

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* pa = (A*)operator new(sizeof(A));
	//pa->A();//error錯(cuò)誤調(diào)用方式,構(gòu)造函數(shù)只允許構(gòu)造時(shí)進(jìn)行調(diào)用
	new(pa)A; // 定位new,placement-new,顯示調(diào)用構(gòu)造函數(shù)初始化這塊對(duì)象空間
	A* pb = (A*)operator new(sizeof(A));
	new(pb)A(3);
    A* pc = new A;
	new(pc)A(3);
	// 等于 delete p
	pa->~A(); // 析構(gòu)函數(shù)可以顯示調(diào)用
	operator delete(pa);
	pb->~A();
	operator delete(pb);
    delete pc;
	return 0;
}

大家要知道定位new哦,他是一種對(duì)已經(jīng)創(chuàng)建出來(lái)的對(duì)象,還能繼續(xù)調(diào)用其構(gòu)造函數(shù)的方式。

7.`malloc`/`free`和`new`/`delete`的區(qū)別

??济嬖囶}

8.再次理解內(nèi)存泄漏

首先大家先想一想這個(gè)問(wèn)題:內(nèi)存泄漏是指針丟了還是內(nèi)存丟了?

內(nèi)存管理中,內(nèi)存是用指針去維護(hù)的,當(dāng)你的動(dòng)態(tài)內(nèi)存空間還沒(méi)有釋放時(shí),你已經(jīng)把指針弄丟了,那么你將無(wú)法控制這段空間,進(jìn)而導(dǎo)致內(nèi)存泄漏。

什么是內(nèi)存泄漏,內(nèi)存泄漏的危害

什么是內(nèi)存泄漏:內(nèi)存泄漏指因?yàn)槭韬龌蝈e(cuò)誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并不是指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,因?yàn)樵O(shè)計(jì)錯(cuò)誤,失去了對(duì)該段內(nèi)存的控制,因而 造成了內(nèi)存的浪費(fèi)。

內(nèi)存泄漏的危害:長(zhǎng)期運(yùn)行的程序出現(xiàn)內(nèi)存泄漏,影響很大,如操作系統(tǒng)、后臺(tái)服務(wù)等等,出現(xiàn)內(nèi)存泄漏會(huì) 導(dǎo)致響應(yīng)越來(lái)越慢,最終卡死。

到此這篇關(guān)于C++圖文并茂分析講解內(nèi)存管理的文章就介紹到這了,更多相關(guān)C++內(nèi)存管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論