【C++】RAII思想---利用對象生命週期來控制程序資源

C語言中我們學過指針,那麼爲什麼在C++中還需要存在智能指針呢?

實際上它的出現就是給c++的內存管理“填坑”來的~ 因爲它的內存自己管理,所以說,有的時候使用malloc或者new創建的對象忘記釋放就會導致內存泄漏,又或者此時釋放語句之前有一段代碼是拋異常的話,那麼執行流就會亂跳,導致內存也無法釋放。
比如這一段代碼,若n太大,開闢空間失敗會拋異常,導致執行流跳出沒有釋放指針p。

void Func()
{
	int n;
	cin >> n;
	int *p = new int;
	int *t = new int[n];//失敗時拋異常
	delete p;//沒有釋放p
	delete t;
}

所以c++就引入了智能指針的概念來解決該問題。在瞭解智能指針之前應該先了解RAII思想。

RAII思想

智能指針的核心思想就是RAII(Resource Acquisition Is Initialization),RAII是一種利用對象生命週期來控制程序資源(如內存、文件句柄、網絡連接、互斥量等等)的簡單技術。

RAII是資源獲得即初始化,在對象構造時獲取資源,接着控制對資源的訪問使之在對象的生命週期內始終保持有效,最後在對象析構的時候釋放資源。藉此,我們實際上把管理一份資源的責任託管給了一個對象。這種做法有兩大好處:

  • 不需要顯式地釋放資源。
  • 採用這種方式,對象所需的資源在其生命期內始終保持有效

RAII思想就是把資源交給對象去管理,如下所示: 

template<class T>
class SmartPtr
{
public:
	SmartPtr(T* ptr)
		:_ptr(ptr)
	{}
	~SmartPtr()
	{
		cout <<"delete :"<< _ptr << endl;
		delete[] _ptr;
	}
private:
	T* _ptr;
};

在對象的構造階段把資源交給對象管理,對象的生命週期結束時會自動調用析構函數完成指針的釋放。如圖:拋出的異常被捕獲,同時指針也釋放了。

RAII思想--智能鎖

RAII思想可以擴展到鎖上面,因爲有時候加鎖之後未解鎖拋異常會導致執行流亂跳,而導致鎖未釋放,因此我們也可以基於此寫一個智能鎖,把這個鎖交給一個對象管理,對象出了作用域就會自動調用析構函數完成鎖的釋放。但是這裏需要注意的是,定義成員變量的時候要定義爲引用,這樣才能保證加鎖的時候是加在同一個鎖上的

//定義成模板則若有另外類型的鎖來了也可以用這個SmartLock
template<class T>
class SmartLock
{
public:
	SmartLock( T& lock)
		:_lock(lock)
	{}
	~SmartLock()
	{
		cout << "unlock :" << &_lock << endl;
		_lock.unlock();
	}
private:
	T& _lock;//使用引用,保證加鎖能加在同一個鎖上面
	          //引用定義成員變量,在定義它的時候初始化它
};

//使用
mutex mtx;
void add(int n, int *value)
{
	SmartLock<mutex> smtlock(mtx);//用smtlock對象管理mtx這個鎖,出了作用域會自動解鎖
	for (int i = 0; i < n; i++)
	{
		++(*value);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章