智慧指標實現
原來的記憶體管理程式碼
int main()
{
int *ptr = new(nothrow) int(0); //關閉異常
if(!ptr)
{
cout << "new fails."
return 0;
}
if(!check()) ///有校驗 ,丟擲異常,每次都得管理記憶體
{
delete ptr; //釋放
ptr = nullptr; //防止空懸指標
throw exception();
}
delete ptr; //釋放
ptr = nullptr; //防止空懸指標
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
使用引用計數,實現智慧指標
1.建構函式中計數初始化為1,拷貝建構函式中計數值加1;
2.解構函式中引用計數減一;
3.賦值運算子中,左邊的物件引用計數減一,右邊的物件引用計數加一;
4.在賦值運算子和解構函式中,如果減一後為0,則呼叫delete釋放物件。
/////////////////////////////////////////////////////////////////////////////////////////////
智慧指標即為封裝好的,帶計數的指標,需要實現 建構函式,拷貝構造,賦值構造,析構
#include <iostream>
using namespace std;
template<class T> //模板類T,智慧指標即為封裝好的,帶計數的指標
class SmartPtr
{
public:
SmartPtr(T *p); //建構函式,引數是普通指標
SmartPtr(const SmartPtr<T> &orig); // 拷貝構造 ,淺拷貝
SmartPtr<T>& operator=(const SmartPtr<T> &rhs); // 賦值操作符號,淺拷貝
~SmartPtr() ; //解構函式
private:
T * ptr; // 指標
int *use_count; // 將use_count宣告成指標是為了方便對其的遞增或遞減操作
};
template<class T>
SmartPtr<T>::SmartPtr(T *p) : ptr(p)
{
try
{
use_count = new int(1); //分配計數記憶體
}
catch (...)
{
delete ptr;
ptr = nullptr;
use_count = nullptr;
cout << "Allocate memory for use_count fails." << endl;
exit(1); //退出程式
}
cout << "Constructor is called!" << endl;
}
template<class T>
SmartPtr<T>::~SmartPtr()
{
// 只在最後一個物件引用ptr時才釋放記憶體
if (--(*use_count) == 0)
{
delete ptr;
delete use_count;
ptr = nullptr;
use_count = nullptr;
cout << "Destructor is called!" << endl;
}
}
template<class T>
SmartPtr<T>::SmartPtr( const SmartPtr<T> &orig)
{
ptr = orig.ptr;
use_count = orig.use_count;
++(*use_count);
cout << "Copy constructor is called!" << endl;
}
// 過載等號函式不同於複製建構函式,即等號左邊的物件可能已經指向某塊記憶體。
// 這樣,我們就得先判斷左邊物件指向的記憶體已經被引用的次數。如果次數為1,
// 表明我們可以釋放這塊記憶體;反之則不釋放,由其他物件來釋放。
template<class T>
SmartPtr<T>& SmartPtr<T>::operator = (const SmartPtr<T> &rhs)
{
//這句話如果放在最後面,那麼 rhs=rhs(計數為1的時候),將會釋放記憶體
++(*rhs.use_count);
// 將左運算元物件的使用計數減1,若該物件的使用計數減至0,則刪除該物件
if (--(*use_count) == 0)
{
delete ptr;
delete use_count;
cout << "Left side object is deleted!" << endl;
}
ptr = rhs.ptr;
use_count = rhs.use_count;
cout << "Assignment operator overloaded is called!" << endl;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
使用方法
指向單個元素的 智慧指標,會有預設記憶體釋放器,也可自己定義
shared_ptr<string> str_point ( new string("jutta"),
// 自定義解構函式,lamada表示式
[](string *p)
{
cout << "delete " << *p << endl;
delete p;
}
);
指向陣列元素的 智慧指標,需要自己定義記憶體釋放函式
shared_ptr<int> int_point ( new int[10],
// 自定義解構函式,lamada表示式
[](int *p)
{
delete[] p;
}
);
也可以使用unique_ptr的default_delete函式
shared_ptr<int> int_point (new int[10], default_delete <int [] > () );
share_prt與weak_ptr的區別?