数据结构--智能指针

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构--智能指针相关的知识,希望对你有一定的参考价值。

一 智能指针的示例

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.堆对象的生命周期由智能指针进行管理

以上是关于数据结构--智能指针的主要内容,如果未能解决你的问题,请参考以下文章

如何用智能指针构造树结构?

如何设置 vscode 的代码片段,以便在自动完成后自动触发 vscode 的智能感知?

更新:C++ 指针片段

片段中的ArrayAdapter空指针

片段中的 EditText 上的空指针异常 [重复]

智能指针的实现