C++探索智慧指標
一、 RAII(Resource Acquisition Is Initialization)
資源分配即初始化,定義一個類來封裝資源的分配和釋放,在建構函式完成資源的分配和初始化,在解構函式完成資源的清理,可以保證資源的正確初始化和釋放。
RAII是一種思想,智慧指標是RAII思想的一種應用。
小知識:別的語言都有gc垃圾回收,即在堆上建立的記憶體,在不用這個物件時,會自動回收這些空間,使用智慧指標也可以達到這樣的效果。
智慧指標的定義:
template<class T> class AutoPtr { public: AutoPtr(T* ptr) :_ptr(ptr) { } ~AutoPtr() { printf("_ptr:%p\n", _ptr);//檢測是否析構 delete _ptr; } private: T *_ptr; };
我們知道,一般程式下,若出現異常,程式回終端,則不回走到delete,就造成了記憶體洩漏。若用智慧指標,將建立的指標的地址傳入智慧指標,出了類的作用域,物件會自動析構,所以開闢的空間也會析構。不管會不會遇到異常,還可以解決忘記delete的諸多問題,減輕了程式設計師的負擔。
#include"smartPstr.hpp" void DoSomeThing() { throw string("拋異常"); } void testSm() { AutoPtr<int> ap1(new int(2)); DoSomeThing(); } int main() { try { testSm(); } catch (string s) { cout << s << endl; } return 0; }
所以智慧指標有兩個特性:1、滿足RAII思想 2、像一個指標 3、深淺拷貝
所以現在的問題是指標有何特性,若何時智慧指標更像一個指標。
解決深淺拷貝
1、auto_ptr
管理權轉移的辦法
但是管理權轉移是有缺陷的設計,一般不清楚內部設計的會認為被轉移許可權的指標還存在,容易導致空指標的問題出現,所以很多公司的內部文件明確規定不要使用auto_ptr.
2、Scoped_ptr: 它的設計理念就是防拷貝,簡單粗暴。
將拷貝構造和賦值運算子過載定義為私有且不實現,就可做到防拷貝。
3、SharedPtr 共享指標: 引用計數
template<class T>
class SharedPtr
{
public:
SharedPtr(T * pty)
:_ptr(pty)
, _pcount(new int(1))
{
}
SharedPtr(const SharedPtr<T>& sp)
{
_ptr = sp._ptr;
_pcount = sp._pcount;
(*(_pcount))++;
}
~SharedPtr()
{
if (--(*_pcount) == 0)
{
printf("_ptr:%p\n", _ptr);
delete _ptr;
delete _pcount;
}
}
SharedPtr<T>& operator=(SharedPtr<T>& sp)
{
if (this != &sp)
{
if (--(*_pcount) == 0)
{
delete _ptr;
delete _pcount;
}
_ptr = sp._ptr;
_pcount = sp._pcount;
(*_pcount)++;
}
return *this;
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
protected:
T * _ptr;
int* _pcount;
};
4、weakPtr 解決迴圈引用 weak_ptr是為配合shared_ptr而引入的一種智慧指標來協助shared_ptr工作,它可以從一個shared_ptr或另一個weak_ptr物件構造,它的構造和析構不會引起引用記數的增加或減少。沒有過載*和->但可以使用lock獲得一個可用的shared_ptr物件
二、探索shared_ptr
上一部分實現的簡化版sharedptr看起來不錯,起始還有存在以下問題;
1、引用計數更新存線上程安全問題
2、迴圈引用問題;
3、定置刪除器;
知識點:仿函式----函式物件 一個類過載(),可以用這個物件來實現傳參