C++智能指標管理類__C++

來源:互聯網
上載者:User
1.程式員明確的進行記憶體釋放

對於c++程式員,最頭腦的莫過於對動態分配的記憶體進行管理了。c++在堆上分配的記憶體,需要程式員負責對分配的記憶體進行釋放。但有時記憶體的釋放看起來並不件很輕鬆的事,如下程式

void func(){    int *p = new int(0);    if(一些判斷)    {        return;    }    p = new int(1);    delete p;}


這個函數沒有任何意義,只為說明問題。func函數至少有三處問題。1.一旦if的判斷條件成立,就會立馬執行返回語句。此時p所指向的記憶體將無法釋放(這個新手一般都會犯的錯誤)。2. p = new int(1);語句,沒有將原來分配在堆上的記憶體釋放,造成原來那塊記憶體永遠不可能釋放直到程式結束。3.這個問題並不是那麼明顯,假設func()函數的代碼很長。

void func(){    int *p = new int(0);    ...    delete p;}

在int *p = new int(0)和delete p之間有大量代碼,而這中間的代碼可能有代碼已經執行過delete p,並且沒有把p置0。此時p為懸掛指標。後面再執行delete p就會造成執行階段錯誤。 2.一個類似於boost shared_ptr的智能指標管理類

下面是參照c++ primer及effective c++自己寫的一個智能指標管理類。使用SmartPtr,就不再需要關心記憶體的釋放問題了。

#ifndef SMARTPTR_INCLUDE_H#define SMARTPTR_INCLUDE_H#include <iostream>using namespace std;namespace commutil{    template<typename T>    class SmartPtr    {    public:        SmartPtr(T *p = 0);        SmartPtr(const SmartPtr &);        SmartPtr &operator=(const SmartPtr &);        ~SmartPtr();        T &operator *();        T *operator ->();    private:        void decreaseRef();        T *m_p;        int *m_useCnt;    };    template<typename T>    SmartPtr<T>::SmartPtr(T *p=0):m_p(p)    {        //調用此建構函式時,預設引用數為1        m_useCnt = new int(1);    }    template<typename T>    SmartPtr<T>::SmartPtr(const SmartPtr &rhs)    {        //使用複製建構函式,建立新的對象,引用數加1        this->m_p = rhs.m_p;        this->m_useCnt = rhs.m_useCnt;        (*m_useCnt)++;    }    template<typename T>    SmartPtr<T>::~SmartPtr()    {        decreaseRef();    }    template<typename T>    void SmartPtr<T>::decreaseRef()    {        if(--(*m_useCnt)==0)        {//當引用數為0時,釋放heap記憶體            delete m_useCnt;            delete m_p;        }    }    template<typename T>    T &SmartPtr<T>::operator *()    {        //重載解引用符        return *m_p;    }    template<typename T>    T *SmartPtr<T>::operator ->()    {        //重載 ->運算子,返回真實的對象指標        return m_p;    }    template<typename T>    SmartPtr<T> &SmartPtr<T>::operator=(const SmartPtr &anotherPtr)    {        if(this==&anotherPtr)        {//防止自賦值            return *this;        }        //使用賦值運算子,原來所指對象的引用數減1。        decreaseRef();        m_p = anotherPtr.m_p;        m_useCnt = anotherPtr.m_useCnt;        ++*m_useCnt;//指向新的對象,所指對象引用數加1        return *this;    }}#endif

3.使用SmartPtr的案例分析
3.1第一個SmartPtr的執行個體

void func(){    SmartPtr<int> autoPtr(new int(1));}

在func中,定義了SmartPtr的一個對象autoPtr,並用new int(1)在堆上分配一塊記憶體,將分配的記憶體首地址傳給SmartPtr的建構函式。此時autoPtr的m_useCnt的值為1。當func執行完成時,autoPtr對象超出其範圍,調用autoPtr的解構函式。在解構函式中調用私人的decreaseRef()函數,在decreaseRef()中將autoPtr的m_useCnt所記憶體值減1;此時m_useCnt所指記憶體值為0,執行delete m_useCnt;delete m_p;。至此在建立autoPtr對象時動態分配的記憶體被釋放。


3.2帶有return語句的SmartPtr

void func(){    SmartPtr<int> autoPtr(new int(1));    if(判斷條件)    {        return;    }}

func()函數中的if判斷條件成立時,執行return;語句後,autoPtr超出其作用範圍,記憶體釋放。分析見3.1
3.3 SmartPtr對象管理新的SmartPtr對象
    SmartPtr<int> autoPtr1(new int(0));    SmartPtr<int> autoPtr2(new int(1));    autoPtr1 = autoPtr2;

執行autoPtr1 = autoPtr2,由於SmartPtr類重載了賦值運算子。實際執行的是SmartPtr的operator=()函數,在上面這個指派陳述式中,先autoPtr1的m_useCnt所指記憶體值減1。此時m_useCnt所指記憶體值變為0,執行m_p所指記憶體釋放。使用SmartPtr解決了1中所提的第二個問題。並且所有記憶體管理與釋放工作都由SmartPtr進行,程式員不需要再關心什麼時候進行記憶體釋放。


3.4SmartPtr共用對象資源

與auto_ptr不同,SmartPtr使用引用計數機制保證多個SmartPtr對象可以管理同一個對象資源

void func(){    SmartPtr<int> autoPtr1(new int(0));    SmartPtr<int> autoPtr2(autoPtr1);}
執行SmartPtr autoPtr2(autoPtr1)調用SmartPtr的拷貝建構函式,在拷貝建構函式中將autoPtr2的m_useCnt及m_p分別指向autoPtr1所指向的記憶體,再將m_useCnt的引用數加1。func()函數結束時,兩次調用SmartPtr的解構函式,兩次解構函式後引用數為0,刪除m_useCnt,m_p所指記憶體。
3.5SmartPtr訪問類成員函數
class A{public:    void print()    {        cout<<"A"<<endl;    }};void func(){    A *obj = new A();    obj->print();    delete obj;}

SmartPtr重載了->運算子,可以將SmartPtr對象像指標一樣訪問成員函數。

void func(){    SmartPtr<A> autoPtr(new A());    autoPtr->print();}

4.小結

SmartPtr類實現了記憶體對象”自管理”,使用SmartPtr程式員不再需要關心動態記憶體的釋放問題。與shared_ptr不同,SmartPtr類只能管理指標類型的資源,並且SmartPtr不支援自訂的資源釋放函數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.