智能指針---shared_ptr和weak_ptr

智能指針主要解決被多個對象引用時,資源如何釋放的問題。

下面介紹一下boost庫中的shared_ptr和weak_ptr:

Shared_ptr:當進行拷貝和賦值操作時, shared_ptr所指向的對象的引用計數都會增加,一旦變爲0,就會自動釋放自己管理的對象。(shared_ptr所指向的對象有一個被釋放時,引用計數就會減1)

Weak_ptr: weak_ptr是一種不控制所指向對象生存週期的智能指針,它指向一個shared_ptr管理的對象時,並不會改變對象的引用計數(引用計數不增加),一旦最後一個指向shared_ptr的對象被銷燬,對象就會被釋放,即使有weak_ptr指向該對象,還是會被釋放。

當創建一個weak_ptr時,要用一個shared_ptr來初始化,由於對象可能不存在,我們不能使用weak_ptr來訪問對象,通過調用lock()方法,檢查對象是否存在,若存在,則返回一個指向共享對象的shared_ptr.

原理:在創建共享對象時,要使用強指針 shared_ptr,若將該對象給其他線程時,則需要將強指針 shared_ptr轉化爲弱指針weak_ptr
(強指針的引用計數會增加,不轉化爲弱指針則一旦被其他線程調用,則該對象將一直不能析構,weak_ptr對象引用資源不會增加引用計數)要是弱指針weak_ptr想訪問該對象時,不能通過weak_ptr來直接訪問資源,需要進行提升(shared_ptr能保證自己沒被釋放之前,所管理的資源是不會被釋放的,當shared_ptr引用計數爲0時,釋放資源,即使有weak_ptr指向它,而weak_ptr通過lock()方法來判斷所管理的資源是否被釋放,訪問時要進行提升)weak_ptr爲shared_ptr,將該弱指針提升爲強指針,若提升成功,指針不爲空,否則爲空。

這裏寫圖片描述

重磅推薦《linux多線程服務器編程》—第一章1.6節 神器shared_ptr/weak_ptr 書目作者陳碩(很膩害的一個大神)

附上一個自己實現的智能指針,通過鏈表來存儲這些被引用的資源,當我們在實現指針的拷貝,賦值,析構等操作時,資源引用計數會相應的增加和減少。會遍歷鏈表找到該資源的類型,對該資源計數引用增加減少,若計數減少爲0時,則釋放該資源節點。

//智能指針
class HeapTable//給資源上的指針計數
{
public:
     static HeapTable *Getinstance()//單例  不同類型實例化只能在同一個鏈表
     {
             static HeapTable  mHeapTable;
             return &mHeapTable;
     }
     ~HeapTable()
     {
         Node *pcur=phead;
         while (pcur != NULL)
         {
             phead=phead->mpnext;
             delete pcur;
             pcur=phead;
         }
     }
    void addRef(void *ptr)
    {
        Node *pcur=phead->mpnext;
        while (pcur != NULL)
        {
            if (pcur->paddr == ptr)//查找到對該資源計數器加1
            {
                pcur->mcount++;
                return;
            }
            pcur=pcur->mpnext;
        }
        pcur=new Node;//沒查找到 進行頭插
        pcur->mpnext=phead->mpnext;
        phead->mpnext=pcur;

    }
    void delRef(void *ptr)
    {
        Node *pcur=phead->mpnext;
        while (pcur != NULL)
        {
            if (pcur->paddr == ptr)//查找到對該資源計數器減1
            {
                pcur->mcount--;
                return;
            }
            pcur=pcur->mpnext;
        }
    }
    int GetRef(void *ptr)
    {
        Node *pcur=phead->mpnext;
        while (pcur != NULL)
        {
            if (pcur->paddr == ptr)
            {
                return pcur->mcount;
            }
            pcur=pcur->mpnext;
        }
        return -1;
    }

private:
    HeapTable(){phead = new Node;}
    class Node
    {
    public:Node(void *ptr=NULL):mcount(0),paddr(ptr),mpnext(NULL)
           {
               if (paddr != NULL)
               {
                   mcount=1;
               }
           }
        int mcount;
        void *paddr;//指向資源
        Node *mpnext;
    };
    Node *phead;
};

template<typename T>
class CsmartPtr
{
public:
    CsmartPtr(T* str = NULL):mpstr(str)//構造
    {
        if (mpstr != NULL)
        {
            addRef();
        }
    }

    CsmartPtr(const CsmartPtr<T> &src):mpstr(src.mpstr)//拷貝構造
    {
        if (mpstr != NULL)
        {
            addRef();
        }
    }

    CsmartPtr<T>& operator=(const CsmartPtr<T> &src)//賦值運算符重載
    {
        if (this == &src)//防止自賦值
        {
            return *this;
        }
        if (mpstr != NULL)//釋放原來的空間
        {
            delRef();
            if (GetRef() == 0)
            {
                delete mpstr;
                mpstr=NULL;
            }   
        }

        mpstr=src.mpstr;
         addRef();
        return *this;
    }

    ~CsmartPtr()
    {
        cout<<"this"<<this<<endl;
        delRef();
        if (GetRef() == 0)
        {
            delete mpstr;
            mpstr=NULL;
        }
    }

    T & operator *(){return *mpstr;}
    const T & operator *()const{return *mpstr;}

    T* operator ->(){return mpstr;}
    const T * operator ->()const{return mpstr;}

    void addRef(){ mpHeapTab->addRef(mpstr);}
    void delRef(){ mpHeapTab->delRef(mpstr);}
    int GetRef() {return mpHeapTab->GetRef(mpstr);}


private:
    T *mpstr;
    static HeapTable *mpHeapTab;//靜態指針
};

//靜態變量在全局進行初始化
template<typename T>
HeapTable*CsmartPtr<T>::mpHeapTab=HeapTable::Getinstance();

int main()
{
    int *p = new int;

    CsmartPtr<int>pointer1(new int);
    CsmartPtr<int>pointer2(new int);
    CsmartPtr<int>pointer3(pointer1);
    pointer2=pointer1;

    CsmartPtr<char> pointer4((char*)p);

    return 0;
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章