智能指针SmartPointer和SharedPointer实现

之前已经实现了一个智能指针类,为什么还要再论智能指针呢?
之前设计的SmartPointer的设计方案:
(1)指针生命周期结束时主动释放堆空间;
(2)一片堆空间最多只能由一个指针标识;
(3)杜绝指针运算和指针比较。

思考:
如何实现 SharedPointer 使得多个智能指针对象可以指向同一片堆内存 , 同时支持堆内存的自动释放?

设计思路:
这里写图片描述
Pointer继承自Object,只要不实现析构函数,那么Pointer这个类就是一个抽象类。实现方式:

#ifndef _POINTER_H_
#define _POINTER_H_

#include "Object.h"

namespace DTLib
{
    template < typename T >

    class Pointer : public Object
    {
    protected:
        T* m_pointer;

    public:
        Pointer(T* p = NULL)
        {
            m_pointer = p;
        }

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

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

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

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


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

        T* get() const
        {
            return m_pointer;
        }

    };
}

#endif

重新实现SmartPointer:

#ifndef _SMARTPOINTER_H_
#define _SMARTPOINTER_H_

#include "Pointer.h"

namespace DTLib
{
    template <typename T>

    class SmartPointer : public Pointer<T>
    {
    public:
        SmartPointer(T* p = NULL) : Pointer<T>(p)
        {

        }

        SmartPointer(const SmartPointer<T>& obj) : Pointer<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; // 要保证异常安全

                this->m_pointer = obj.m_pointer;

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

                delete p; // 保证异常安全
            }

            return *this; 
        }

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

    };

}

#endif

SharedPointer的设计要点:
通过计数机制ref标识堆内存:
1、堆内存被指向时 : ref++;
2、指针被置空时 :ref –;
3、ref==0时 :释放堆内存。

这里写图片描述
代码实现:
(1)实现拷贝构造时,自身的m_ref要挂接到被拷贝的对象上去;
(2)实现赋值操作时,说明不再指向原来的堆空间,自身的m_ref要减减,为空时要释放指针指向的空间和计数机制的空间;
(3)析构函数里要调用clear函数实现堆空间内存自动释放。
核心是下面的clear函数的实现,同时要注意保证程序的异常安全。

#ifndef _SHAREDPOINTER_H_
#define _SHAREDPOINTER_H_

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

namespace DTLib
{
    template < typename T >

    class SharedPointer : public Pointer<T>
    {
    protected:
        int* m_ref; // 计数机制贯穿SharedPointer类实现的全过程,实现的时候要主要这些细节。

    public:
        SharedPointer(T* p = NULL) : m_ref(NULL)
        {
            if (p)
            {
                this->m_ref = static_cast<int*>(std::malloc(sizeof(int)));

                if (this->m_ref)
                {
                    (*m_ref) = 1;
                    this->m_pointer = p;
                }
                else
                {
                    THROW_EXCEPTION(NoEnoughMemoryException, "No memery to create SharedPointer object ...");
                }
            }
        }

        SharedPointer(const SharedPointer<T>& obj) : Pointer<T>(NULL)
        {
            this->m_ref = obj.m_ref; // 自身的m_ref要挂接到被拷贝的对象上去
            this->m_pointer = obj.m_pointer;

            if (this->m_ref)
            {
                (*this->m_ref)++; 
            }
        }

        SharedPointer<T>& operator= (const SharedPointer<T>& obj)
        {
            if (this != &obj)
            {
                clear();

                this->m_ref = obj.m_ref;
                this->m_pointer = obj.m_pointer;

                if (this->m_ref)
                {
                    (*this->m_ref)++;
                }
            }
            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();
        }
    };
}

#endif

小结:
(1)SharedPointer最大程度的模拟了原生指针的行为;
(2)计数机制确保多个智能指针合法的指向同一片堆空间;
(3)智能指针只能用于指向堆空间中的内存;
(4)不同类型的智能指针不要混合使用;
(5)堆对象的生命周期由智能指针进行管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值