欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

驗證棧是向下生長的

#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;
}

驗證堆一般是向上生長的(不一定)

#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的地址高的(因為堆一般是向上生長的),但是有時候是不一定的。

鞏固內(nèi)存管理知識點

答案

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

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

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

malloccallocrealloc

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

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

異地增容–后面沒有足夠的空間

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

//C++開辟動態(tài)內(nèi)存的新玩法
//語法演示:
#include<iostream>
using namespace std;
int main()
{
	//申請一個int的動態(tài)空間
	int* p1 = (int*)malloc(sizeof(int));
	*p1 = 1;
	int* p2 = new int(2);//這里是初始化
	free(p1);
	delete p2;
	//申請一個10各int的動態(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語言的版本相比,c++的版本,初始化時顯得比較方便,而且語法比較簡潔。當(dāng)然了,更大的優(yōu)越性還在后面。

開辟自定義類型的空間(請用vs2013以上版本測試代碼)

#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()
{
	//申請一個結(jié)點的空間
    ListNode* pa = (ListNode*)malloc(sizeof(ListNode)*4);
	ListNode* pb = new ListNode(1);//不用去用sizeof去計算空間大小,很方便   
	free(pa);
	delete pb;
	//申請4個結(jié)點的空間--當(dāng)然了一般不會這么玩兒,我們只是看看效果
	ListNode* pc = (ListNode*)malloc(sizeof(ListNode)* 4);
	ListNode* pd = new ListNode[4]{1, 2, 3, 4};
	free(pc);
	delete[]pd;
	return 0;
}

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

總結(jié)一下

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

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

我:cpu過來遭罪

cpu:你不要過來啊

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

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

將項目屬性修改一下,改成64位平臺即可,64位平臺有2^34 G的空間(虛擬內(nèi)存)在這我們不做細(xì)說,因為我也不太了解Linux。

4.了解operator new和operator delete

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

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

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

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

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

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是完全一樣的,功能都是在堆上申請釋放空間
	// 失敗了處理方式不一樣,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,程序還會繼續(xù)向下執(zhí)行,但是operator new失敗,就會報異常,f函數(shù)后面的沒有在繼續(xù)執(zhí)行,然后走進catch語句中。

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;
}

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

我們是可以通過反匯編來看效果的

6.定位new–placement-new

通過上述的學(xué)習(xí)我們知道,malloc,和operator是不會去調(diào)用構(gòu)造函數(shù)的,new會去調(diào)用構(gòu)造函數(shù),而且構(gòu)造函數(shù)是只允許構(gòu)造出對象時調(diào)用,而你的對象創(chuàng)建出來之后是無法調(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錯誤調(diào)用方式,構(gòu)造函數(shù)只允許構(gòu)造時進行調(diào)用
	new(pa)A; // 定位new,placement-new,顯示調(diào)用構(gòu)造函數(shù)初始化這塊對象空間
	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哦,他是一種對已經(jīng)創(chuàng)建出來的對象,還能繼續(xù)調(diào)用其構(gòu)造函數(shù)的方式。

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

??济嬖囶}

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

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

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

什么是內(nèi)存泄漏,內(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)存泄漏的危害:長期運行的程序出現(xiàn)內(nèi)存泄漏,影響很大,如操作系統(tǒng)、后臺服務(wù)等等,出現(xiàn)內(nèi)存泄漏會 導(dǎo)致響應(yīng)越來越慢,最終卡死。

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

相關(guān)文章

最新評論