一、為什麼要有智能指針?
因為在平時程式設計過程中,極大可能會出現兩種情況;
(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;
不支援重載,隻是看起來像一個指針而已;