新智能指針的加入:
C++11之前,智能指針只有 auto_ptr 一種,但是後來發現它並不能很好的保證指針的安全可靠性,隨之又出現了
shared_ptr unique_ptr weak_ptr scope_ptr 這幾種智能指針。
假如存在這樣的代碼
int main()
{
SmartPtr<int> sp1(new int);
SmartPtr<int> sp2(sp1);
*sp1 = 20;
return 0;
}
這裏,SmartPtr即爲之前博客實現的auto_ptr,顯而易見,*sp1=20;這行會出現崩潰。
解決方案:
之前的auto_ptr,管理權唯一,釋放權也唯一,現在要使智能指針管理權不唯一,釋放權唯一。
帶有標誌位(flag)的智能指針
如圖:
代碼:
#include<iostream>
using namespace std;
template<typename T>
class SmartPtr
{
public:
SmartPtr(T* ptr) :mptr(ptr)
{
flag = true;
}
SmartPtr(const SmartPtr<T>& rhs):mptr(rhs.mptr)
{
flag = rhs.flag;
rhs.flag = false;
}
SmartPtr<T>& operator=(const SmartPtr<T>& rhs)
{
if (this != &rhs)
{
~SmartPtr();
mptr = rhs.mptr;
flag = rhs.flag;
rhs.flag = false;
}
return *this;
}
~SmartPtr()
{
if (flag)
{
delete mptr;
}
mptr = NULL;
}
T& operator*()
{
return *mptr;
}
T* operator->()
{
return mptr;
}
private:
T* mptr;
mutable bool flag;//去除常性
};
int main()
{
SmartPtr<int> sp1(new int);
SmartPtr<int> sp2(sp1);
SmartPtr<int> sp3(sp1);
*sp1 = 20;
return 0;
}
這裏程序不會崩潰,有釋放權的只有sp2。
又一個問題
因爲釋放權的轉移,有可能導致堆內存被提前釋放
void func(SmartPtr<int> sp)//實參傳形參 調用拷貝構造
{
}
int main()
{
SmartPtr<int> sp1(new int);
SmartPtr<int> sp2(sp1);
SmartPtr<int> sp3(sp1);
func(sp2);//;執行結束後,形參對象銷燬 相當於堆內存已經歸還給系統
*sp1 = 20;//使用不可使用的內存塊 野指針 該內存塊可能被再分配
return 0;
}
調用這個函數,實參傳形參 調用拷貝構造,func(sp2);//;執行結束後,形參對象銷燬 相當於堆內存已經歸還給系統。
*sp1 = 20;//使用不可使用的內存塊 野指針 該內存塊可能被再分配,會出現不可預期的數據錯誤。
解決: ScopePtr 不允許多個智能指針對象指向同一塊堆內存
#include<iostream>
using namespace std;
template<typename T>
class ScopePtr//不允許多個智能指針對象指向同一塊堆內存
{
public:
ScopePtr(T* ptr=NULL):mptr(ptr)
{
//mptr = ptr;
}
~ScopePtr()
{
delete mptr;
mptr = NULL;
}
T& operator*()
{
return *mptr;
}
T* operator->()
{
return mptr;
}
private:
ScopePtr(const ScopePtr<T>& rhs);//不需要調用,因爲不允許多個智能指針對象指向同一塊堆內存
ScopePtr<T>& operator=(const ScopePtr<T>& rhs);//不允許多個智能指針對象指向同一塊堆內存
private:
T* mptr;
};
int main()
{
int* p = new int;
ScopePtr<int> sp1(p);
ScopePtr<int> sp2(p);
ScopePtr<int> sp3(p);//後構造的先析構
return 0;
}
int* p = new int;
ScopePtr<int> sp1(p);
ScopePtr<int> sp2(p);
ScopePtr<int> sp3(p);//後構造的先析構
這個程序會崩潰,後構造的先析構,然後先構造的再析構時,delete野指針,程序崩潰。