智能指針shared_ptr

一、 原理 :RAII 資源獲取即初始化技術

原理:接受一個申請好的內存地址,構造一個保存在棧上的智能指針對象,當程序退出棧的作用域範圍後,由於棧上的變量自動被銷燬,智能指針內部保存的內存也就被釋放掉了(除非將智能指針保存起來)。

爲什麼這麼6呢?

在傳統 C++ 中,『記得』手動釋放資源,總不是最佳實踐。因爲我們很有可能就忘記了去釋放資源而導致泄露。所以通常的做法是對於一個對象而言,我們在構造函數的時候申請空間,而在析構函數(在離開作用域時調用)的時候釋放空間,也就是我們常說的 RAII 資源獲取即初始化技術。

#include <iostream>
#include <memory>
using namespace std;

class CData
{
public:
	CData(int iSize) :m_iSize(iSize)
	{
	}
public:
	int m_iSize;
	static CData* m_CDataModule;
};

CData* CData::m_CDataModule = new CData(19);

bool PtrIsNull()
{
	if(NULL == CData::m_CDataModule)
	{
		return false;
	}
	return true;
}
void TestFunc()
{
	bool bResult = PtrIsNull();
	cout <<"01 CData::m_CDataModule->m_iSize " << CData::m_CDataModule->m_iSize << endl;
	shared_ptr<CData> shPtrA(CData::m_CDataModule);
}
int main()
{
	TestFunc();
	bool bResult = PtrIsNull();
	cout << "02 CData::m_CDataModule->m_iSize " << CData::m_CDataModule->m_iSize << endl;
	int iCount = 0;
	
	cin.get();
	return 0;
}

這是在使用智能指針之前

01 CData::m_CDataModule->m_iSize 19
02 CData::m_CDataModule->m_iSize 19

使用智能指針之後,程序第二次輸入雜亂無章的數值,是因爲堆空間被釋放掉了

01 CData::m_CDataModule->m_iSize 19
02 CData::m_CDataModule->m_iSize -572662307

注意PtrIsNull()返回的是 true,這是因爲智能指針對堆空間進行了釋放,但是對原來的指針沒有進行操作

二、引用計數

引用計數是這樣一個技巧,記錄同一個實例被引用的次數,當引用次數大於0時可用,等於0時釋放內存。引用計數的使用常有兩個目的:

  • 簡化跟蹤堆中(也即C++中new出來的)的對象的過程。一旦一個對象通過調用new被分配出來,記錄誰擁有這個對象是很重要的,因爲其所有者要負責對它進行delete。但是對象所有者可以有多個,且所有權能夠被傳遞,這就使得內存跟蹤變得困難。引用計數可以跟蹤對象所有權,並能夠自動銷燬對象。可以說引用計數是個簡單的垃圾回收體系。這也是本文的討論重點。
  • 節省內存,提高程序運行效率。如何很多對象有相同的值,爲這多個相同的值存儲多個副本是很浪費空間的,所以最好做法是讓左右對象都共享同一個值的實現。C++標準庫中string類採取一種稱爲”寫時複製“的技術,使得只有當字符串被修改的時候才創建各自的拷貝,否則可能(標準庫允許使用但沒強制要求)採用引用計數技術來管理共享對象的多個對象。
#include <iostream>
#include <memory>
using namespace std;

class CData
{
public:
	CData(int iSize) :m_iSize(iSize)
	{
	}
public:
	int m_iSize;
	static CData* m_CDataModule;
};

CData* CData::m_CDataModule = new CData(19);

int main()
{
	shared_ptr<CData> shaPtrCDataA(CData::m_CDataModule);
	shared_ptr<CData>  shaPtrCDataB = shaPtrCDataA;

	cout << "Now Use Count"<< shaPtrCDataB.use_count() << endl;

	shared_ptr<CData>  shaPtrCDataC= shaPtrCDataB;
	cout << "Now Use Count" << shaPtrCDataB.use_count() << endl;

	shaPtrCDataA.reset();
	cout << "Now Use Count" << shaPtrCDataB.use_count() << endl;
	cin.get();
	return 0;
}

輸出如下:

Now Use Count2
Now Use Count3
Now Use Count2
在這裏reset執行一次,引用次數就少一次

發佈了195 篇原創文章 · 獲贊 41 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章