天天看點

c++智能指針及RAII機制的了解

一、為什麼要有智能指針?

因為在平時程式設計過程中,極大可能會出現兩種情況;

(1)malloc出來的空間,沒有進行釋放,存在記憶體洩漏;

(2)如果在malloc和free之間抛異常,那麼同樣存在記憶體洩漏問題。該問題稱為異常安全問題。

使用智能指針可以解決跳出函數要頻繁delete的問題,保證記憶體不洩漏,且通過析構函數來釋放資源,使通路記憶體更加安全。

二、智能指針原理及使用

1、智能指針的實作是基于RAII(資源擷取即初始化)。即對象在構造時擷取資源,且在對象的聲明周期内資源始終有效,最後在對象析構的時候釋放資源。即将一份資源管理的責任交給了一個對象。

2、使用RAII思想設計簡單智能指針類

#include<iostream>
using namespace std;

//智能指針的簡單實作
template<class T>
class SmartPtr
{
public:
	SmartPtr(T*ptr = nullptr)
		:_ptr(ptr)
	{}

	~SmartPtr()
	{
		if (_ptr)
		{
			delete _ptr;
		}
	}
	T& operator*()
	{ 
		return *_ptr; 
	}
	T* operator->()//傳回指向空間的内容
	{ 
		return _ptr; 
	}
private:
	T* _ptr;
};
//使用方式

void MergeSort(int *a, int n)
{
int*tmp = (int*)malloc(sizeof(int)*n);
SmartPtr<int> sp(tmp);//把tmp指針委托給sp對象
	//……
}
//主要就是展現了智能指針可以構造時初始化,析構時釋放資源
           

3、智能指針的原理總結

1、RAII特性

2、重載operator*和operator->,具有指針一樣的行為。

三、幾種智能指針

庫裡提供的的智能指針的頭檔案 <memory>

1、std::auto_ptr:

缺點:拷貝構造時,會将之前的指針賦空,導緻之前的指針不能再用。

auto_ptr<int>ptr(new int);

auto_ptr<int>ptr1(ptr);

//注意此時ptr失效

1

2

3

2、std::unique_ptr;

也是智能指針但是不支援靠拷貝(片面解決了上述auto_ptr的問題)

smart_ptr(const smart_ptr &a)=delete(default);

1

3、std::shared_ptr;

原理:使用引用計數的方式來實作多個shared_ptr對象之間的資源共享。

(1)shared_ptr内部,每個資源都維護了一份計數,用來記錄該資源被幾個對象共享;

(2)有對象銷毀時,給計數減1,檢視計數,為0則銷毀,否則不銷毀;

(3)shared_ptr的循環引用問題

兩個智能指針分别指向兩個結點,node1和node2;但是node1是node2的前驅,node2是node1的前驅。

問題: 當node1和node2析構時,分别計數減1,但是_prev和_next還分别指向對應的結點,也就是說_prev釋放了,node2就釋放了,_next釋放了,node1就釋放了。

但是,_prev和_next又分别是node1和node2的成員,是以隻有node1和node2釋放了,_prev和_next才會釋放;

是以,誰也不會釋放;

解決:把節點中的_prev和_next改成weak_ptr就可以了;因為node1->_next = node2;和node2->_prev = node1;時weak_ptr的_next和_prev不會增加node1和node2的引用計數。

4、std::weak_ptr;

不支援重載,隻是看起來像一個指針而已;

繼續閱讀