1. 程式人生 > >數據結構--智能指針

數據結構--智能指針

小結 poi 同時 .sh -o 替換 bject ear malloc

一 智能指針的示例

A.內存泄漏
1.動態申請堆空間,用完後不歸還
2.C++語言中沒有垃圾回收的機制
3.指針無法控制所指堆空間的生命周期
B.當代C++軟件平臺中的智能指針
1.指針生命周期結束時主動釋放堆空間
2.一片堆空間最多只能由一個指針標識
3.杜絕指針運算和指針比較
智能指針的設計方案
a.通過類模板描述指針的行為
能夠定義不同類型的指針對象
b.重載指針特征操作符(->和*)
利用對象模擬原生指針的行為
Point類實現代碼如下

#include "Object.h"

namespace MyLib
{
    template <typename T>
    class Pointer:public Object
    {
    protected:
        T* m_pointer;
    public:
        Pointer(T* p=NULL)
        {
            m_pointer=p;
        }

        T* operator->()
        {
            return m_pointer;
        }

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

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

        T& operator*()
        {
            return *m_pointer;
        }

        bool isNull()const
        {
            return (m_pointer==NULL);
        }

        T* get()const
        {
            return m_pointer;
        }
    };
}

SmartPoint的實現代碼

#include "Pointer.h"
namespace MyLib
{
    /*智能指針的實現(智能指針只能指向單個變量或者單個對象)
        1.指針生命周期結束時主動釋放空間
        2.一片堆空間最多只能由一個指針標識
        3.杜絕指針運算和指針比較

        設計方案
        1.通過類模板描述指針的行為(能夠定義不同類型的指針對象)
        2.重載指針特征操作符(->和*)(利用對象模擬原生指針的行為)
    */
    template<typename T>//創建的指針可以指向任意的類型
    class SmartPointer:public Pointer<T>//定義的類
    {
    public:
        SmartPointer(T* p=NULL):Pointer<T>(p)
        {

        }

        SmartPointer(const SmartPointer<T>& obj)
        {
            this->m_pointer=obj.m_pointer;

            const_cast<SmartPointer<T>&>(obj).m_pointer=NULL;
        }

        SmartPointer<T>& operator =(const SmartPointer<T>& obj)
        {
            if(this!=obj)
            {
                T* p=this->m_pointer;

                //delete m_pointer;

                this->m_pointer=obj.m_pointer;

                const_cast<SmartPointer<T>&>(obj).m_pointer=NULL;

                delete p;
            }

            return *this;
        }

        ~SmartPointer()
        {
            delete this->m_pointer;
        }
    };
}

在使用智能指針(SmartPointer)替換單鏈表(LinkList)中的原生指針會出現問題,可以發現在SmartPointer的設計方案中(一片堆空間最多只能由一個指針標識)

二.SharedPoint的實現

技術分享圖片

SharedPoint設計要點
A.類模板
通過計數機制(ref)標識堆內存
1.堆內存被指向時:ref++
2.指針被置空時:ref--
3.ref==0:釋放堆內存
計數機制的原理
技術分享圖片
同時由於SharedPoint支持多個對象同時指向一片堆空間,因此,必須支持比較操作
實現的代碼如下

#include "Pointer.h"
#include <cstdlib>
#include "Exception.h"

namespace MyLib
{
    template<typename T>
    class SharedPointer :public Pointer<T>
    {
    protected:
        int* m_ref;

        void assign(const SharedPointer<T>& obj)
        {
            this->m_ref=obj.m_ref;
            this->m_pointer=obj.m_pointer;

            if(this->m_ref)
            {
                (*this->m_ref)++;
            }
        }
    public:
        SharedPointer(T* p=NULL):m_ref(NULL)
        {
            if(p)
            {
                this->m_ref=static_cast<int*>(std::malloc(sizeof(int)));//在堆空間申請一個四個字節
                if(this->m_ref)//內存申請成功的情況下的操作
                {
                    *(this->m_ref)=1;
                    this->m_pointer=p;
                }
                else
                {
                    THROW_EXCEPTION(NoEoughMemoryException,"...");
                }
            }
        }

        SharedPointer(const SharedPointer<T>& obj):Pointer<T>(NULL)
        {
            //都指向了堆空間
            assign(obj);
        }

        SharedPointer<T>& operator=(const SharedPointer<T>& obj)
        {
            if(this!=&obj)//避免自賦值
            {
                clear();//在進行賦值之前  將當前的智能指針對象置空

                assign(obj);
            }

            return *this;
        }

        void clear()
        {
            T* toDel=this->m_pointer;
            int* ref=this->m_ref;

            this->m_pointer=NULL;
            this->m_ref=NULL;

            if(ref)
            {
                (*ref)--;

                if(*ref==0)
                {
                    free(ref);

                    delete toDel;
                }
            }
        }

        ~SharedPointer()
        {
            clear();
        }
    };

    template <typename T>
    bool operator == (const SharedPointer<T>& l,const SharedPointer<T>& r )
    {
        return (l.get()==r.get());
    }

    template <typename T>
    bool operator != (const SharedPointer<T>& l,const SharedPointer<T>& r )
    {
        return !(l==r);
    }
}

註意:
1.只能指針只能用來指向堆空間中的單個變量
2.不同類型的智能指針對象不能混合使用
3.不要使用delete釋放智能指針指向的堆空間

三.小結

1.SharedPoint最大程度的模擬了原生指針的行為
2.計數機制確保多個智能指針合法的指向同一片堆空間
3.智能指針只能用於指向堆空間中的內存
4.不同類型的智能指針不要混合使用
5.堆對象的生命周期由智能指針進行管理

數據結構--智能指針