溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C++如何解決垃圾回收問題

發(fā)布時間:2022-02-23 13:44:42 來源:億速云 閱讀:379 作者:iii 欄目:web開發(fā)

本篇內(nèi)容介紹了“C++如何解決垃圾回收問題”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

C++引用計數(shù)設(shè)計與分析(解決垃圾回收問題)

1.引言

我們了解到我們在淺拷貝時對帶指針的對象進(jìn)行拷貝會出現(xiàn)內(nèi)存泄漏,那C++是否可以實現(xiàn)像python,JAVA一樣引入
垃圾回收機制,來靈活的來管理內(nèi)存。

遺憾的是C++并不像python、java等編程語言一樣有著垃圾回收機制(Gabage Collector),因此導(dǎo)致了C++中對動態(tài)
存儲的管理稱為程序員的噩夢,出現(xiàn)了內(nèi)存遺失(memory leak)、懸空指針、非法指針存取等問題。

Bjarne本人認(rèn)為:
“我有意這樣設(shè)計C++,使它不依賴于自動垃圾回收(通常就直接說垃圾回收)。這是基于自己對垃圾回收系統(tǒng)的經(jīng)驗,
我很害怕那種嚴(yán)重的空間和時間開銷,也害怕由于實現(xiàn)和移植垃圾回收系統(tǒng)而帶來的復(fù)雜性。還有,垃圾回收將使C+
+不適合做許多底層的工作,而這卻正是它的一個設(shè)計目標(biāo)。但我喜歡垃圾回收的思想,它是一種機制,能夠簡化設(shè)計、
排除掉許多產(chǎn)生錯誤的根源。

C++中提供的構(gòu)造函數(shù)和析構(gòu)函數(shù)就是為了解決了自動釋放資源的需求。Bjarne有一句名言,“資源需求就是初始化(Resource Inquirment Is Initialization)”。
因此,我們可以將需要分配的資源在構(gòu)造函數(shù)中申請完成,而在析構(gòu)函數(shù)中釋放已經(jīng)分配的資源。
在C++中,允許你控制對象的創(chuàng)建,清楚和復(fù)制,我們就可以通過開發(fā)一種稱為引用計數(shù)的垃圾回收機制實現(xiàn)這種控制

2.設(shè)計思想

首先我們明確在對存在指針的對象構(gòu)造時,析構(gòu)對象時需要把指針delete(釋放掉),但是此時如果我們對對象進(jìn)行淺拷貝,沒有新的指針new。
析構(gòu)對象時候會出現(xiàn)內(nèi)存泄漏(一個指針?biāo)傅膬?nèi)存被兩次釋放的清況),我們用通過引用計數(shù)來解決這個問題:

每構(gòu)造一個對象,就創(chuàng)建一個新的計數(shù)器并+1.每拷貝構(gòu)造一次就在被拷貝的那個對象所在的計數(shù)器上+1;
析構(gòu)時候 按照構(gòu)造函數(shù)析構(gòu)的順序(后造先放,類似棧),最后構(gòu)造或拷貝的先釋放;
每次釋放先對計數(shù)器-1并判斷計數(shù)器是否為0(是否存在淺拷貝的對象),大于0時,繼續(xù)按照析構(gòu)順序析構(gòu)下一個對象;
當(dāng)計數(shù)器為0時,釋放指針。

3.舉例

我們按順序構(gòu)造3個對象,計數(shù)器標(biāo)號記為 1,2,3,對第一個和第三個對象淺拷貝兩次,
對對象拷貝完成后計數(shù)器1,2,3的值分別為 2 1 2.
先釋放計數(shù)器3  計數(shù)器-1后等于1,析構(gòu)掉一個對象。計數(shù)器為 2 1 1
再釋放計數(shù)器1  計數(shù)器-1后等于1,析構(gòu)掉一個對象。計數(shù)器為 1 1 1
再釋放計數(shù)器3  計數(shù)器-1后等于0,析構(gòu)掉一個對象,并釋放掉指針。計數(shù)器為 1    1   空
再釋放計數(shù)器2  計數(shù)器-1后等于0,析構(gòu)掉一個對象,并釋放掉指針。計數(shù)器為 1   空   空
再釋放計數(shù)器1  計數(shù)器-1后等于0,析構(gòu)掉一個對象,并釋放掉指針。計數(shù)器為 空  空   空
最終所有對象析構(gòu)完畢,指針也全部釋放完

4.代碼

//引用計數(shù)類

class CRefCount
{
public: 
	CRefCount();     //構(gòu)造計數(shù)器對象
	CRefCount(const CRefCount& obj); //拷貝構(gòu)造計數(shù)器
	void* Alloc(int size); //構(gòu)造對象時申請空間
	int AddRef();   //計數(shù)增加
	int ReleaseRef();	//計數(shù)減少
	~CRefCount();	

private:
	void* m_pBuf;   //指針緩沖區(qū)
	int* m_pRefCount;  //計數(shù)
};


CRefCount::CRefCount()
{
	m_pBuf = nullptr;
	m_pRefCount = nullptr;
}

CRefCount::CRefCount(const CRefCount& obj)
{
	m_pBuf = obj.m_pBuf;
	m_pRefCount = obj.m_pRefCount;
	AddRef();
}

void* CRefCount::Alloc(int size)
{
	m_pBuf = new char[size + 1];  //申請緩沖區(qū)
	m_pRefCount = new int(0);
	AddRef();      //每次構(gòu)造對象計數(shù)+1

	return m_pBuf;
}

int CRefCount::AddRef()
{
	if (m_pRefCount == nullptr)
		return 0;
	return ++(*m_pRefCount);
}

int CRefCount::ReleaseRef()
{
	if (m_pRefCount == nullptr)
		return 0;

	return --(*m_pRefCount);
}

CRefCount::~CRefCount()
{
	if (ReleaseRef() == 0)
	{
		if (m_pBuf != nullptr)
		{
			delete[] m_pBuf;
			m_pBuf = nullptr;
			delete m_pRefCount;
			m_pRefCount = nullptr;
		}
	}
}

 5.測試

//student測試用例
#include"CRefCount.h"
#include<iostream>
#pragma warning(disable:4996)

using namespace std;

class CStudent
{
private:
	char* m_pName;
	CRefCount m_RefCount;
	const char* GetName() const;
public:
	CStudent(const char* pName);
};


const char* CStudent::GetName() const
{
	return m_pName;
}

CStudent::CStudent(const char* pName)
{
	m_pName = (char*)m_RefCount.Alloc(strlen(pName) + 1);  //申請一個用來存放名字的空間
	strcpy(m_pName, pName);
}


int main()
{
	CStudent s1("shadow");
	CStudent s2("iceice");
	CStudent s3("maybe");
	CStudent s4 = s1;
	CStudent s5 = s3;

	return 0;
}

 調(diào)試這個程序,我們在完成構(gòu)造和拷貝后,查看內(nèi)存,可以看到此時計數(shù)器1,2,3分別對應(yīng)的值為2,1,2

C++如何解決垃圾回收問題

單步跟入,看到第一個拷貝構(gòu)造的對象被析構(gòu)掉,計數(shù)器值-1 ,此時3個計數(shù)器值分別為為2,1,1

 C++如何解決垃圾回收問題

 再繼續(xù)往后走,發(fā)現(xiàn)第二個拷貝對象析構(gòu)掉切指針?biāo)傅膬?nèi)存還未被釋放掉,計數(shù)器1 -1,此時計數(shù)器值為 1,1,1

C++如何解決垃圾回收問題

再向后執(zhí)行,此時第三個構(gòu)造的對象開始被析構(gòu)掉同時計數(shù)器減到0,此時對象3的指針被釋放掉。

 C++如何解決垃圾回收問題

 加上輔助調(diào)試代碼,最終可以看到執(zhí)行結(jié)果,構(gòu)造3次,拷貝2次,釋放3次,完成了引用計數(shù)功能

 C++如何解決垃圾回收問題

“C++如何解決垃圾回收問題”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI