• 第28课 再论智能指针(下)


    1. SharedPointer的设计

    (1)使用类模板,通过计数机制标识堆内存

    (2)堆内存被指向时,(*refCount)++

    (3)指针被置空时:(*refCount)—

    (4)当*refCount == 0时,释放堆内存

    2. 计数机制原理剖析

     

    3. SharedPointer类的声明

    template <typename T>
    class SharedPointer : public Pointer<T>
    {
    protected:
        int* m_refCount; //计数机制成员
    public:
        SharedPointer(T* p = NULL);
        SharedPointer(const SharedPointer<T>& obj);
        
        SharedPointer<T>& operator=(const SharedPointer<T>& obj);
        
        void clear(); //将当前指针置为空
        
        //由于SharedPointer支持多个对象同时指向一片堆空间
        //因此必须支持比较操作!
        bool operator==(const SharedPointer<T>& obj);
        bool operator!=(const SharedPointer<T>& obj);
        
        ~SharedPointer();
    };

    4. 智能指针使用军规

    (1)只能用来指向堆空间中的单个对象(变量)

    (2)不同类型的智能指针对象不能混合使用

    (3)不要使用delete释放智能指针指向的堆空间

    【编程实验】SharedPointer智能指针的实现

    //Pointer.h

    #ifndef _POINTER_H_
    #define _POINTER_H_
    
    #include "Object.h"
    
    namespace DTLib {
    
    template <typename T>
    class Pointer : public Object //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 // _POINTER_H_

    //SharedPointer.h

    #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;
    
        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)++; //计数加1
            }
        }
    public:
        SharedPointer(T *p = NULL) : m_ref(NULL)
        {
            if (p)
            {    //堆空间中申请4个字节的空间
    //
    注意此处不用new,因为int是基本类型不是Object的子类,也就无法享受Object类中重载new的好处,即new int失败时,由于编译器处理方式不同,仍可能是NULL或抛异常。为了统一处理,用malloc
                this->m_ref = static_cast<int*>(malloc(sizeof(int)));
    
                if (this->m_ref)
                {
                    *(this->m_ref) = 1;    //初始化1 ,说明p的堆空间已经有一个sharedpointer指针指向了
                    this->m_pointer = p;
                }
                else
                {    //若malloc不成功,抛出异常
                    THROW_EXCEPTION(NotEnoughMemoryException, "No memory to create SharedPointer object ... ");
                }
            }
        }
    
        SharedPointer(const SharedPointer<T> &obj) : Pointer<T>(NULL)
        { //拷贝构造函数
            assign(obj);
        }
    
        SharedPointer<T> &operator =(const SharedPointer<T> &obj)
        {
            if (this != &obj)
            {    //避免自赋值
                clear(); //  如果当前的sharepointer指针已经指向 另外一片堆空间,
                //应该先置空当前指针,不让它指向任何堆空间
                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不为空指针
                (*ref)--;//释放一个指针减1
    
                if (*ref == 0) //若堆空间没有对应的指针指向
                {
                    free(ref);
    
                    delete toDel;
                }
            }
        }
        //由于SharedPointer支持多个对象同时指向一片堆空间。因此必须支持比较操作!
        bool operator==(const SharedPointer<T>& obj)
        {
            return (this->m_pointer == obj.m_pointer);
        }
    
        bool operator!=(const SharedPointer<T>& obj)
        {
            return (this->m_pointer != obj.m_pointer);
        }
    
        ~SharedPointer()
        {
            clear();
        }
    };
    
    }
    #endif // _SHAREDPOINTER_H_

    //main.cpp

    #include <iostream>
    #include "SharedPointer.h"
    
    using namespace std;
    using namespace DTLib;
    
    class Test : public Object
    {
    public:
        int value;
    
        Test(): value(0)
        {
            cout << "Test()" << endl;
        }
    
        ~Test()
        {
            cout <<"~Test()" << endl;
        }
    };
    
    int main()
    {
        //const SharedPointer<Test> sp0 = new Test();
        SharedPointer<Test> sp0 = new Test();
        SharedPointer<Test> sp1 = sp0;
        SharedPointer<Test> sp2 = NULL;
    
        sp2 = sp1;
    
        sp0->value = 100;
    
        cout << sp0->value << endl;
        cout << sp1->value << endl;
        cout << sp2->value << endl;
    
        //sp1.clear();
    
        cout << (sp0==sp1) << endl;
    
        return 0;
    }
    /*输出结果
    Test()
    100
    100
    100
    1
    ~Test()
    */

    5. 小结

    (1)SharedPointer最大程度的模拟了原生指针的行为

    (2)计数机制确保多个智能指针合法的指向同一片堆空间

    (3)智能指针只能用于指向堆空间中的内存

    (4)不同类型的智能指针不要混合使用

    (5)堆对象的生命周期由智能指针进行管理

  • 相关阅读:
    redis 5.0.5集群部署
    python 继承、多继承与方法重写(二)
    python 脚本监控硬件磁盘状态并发送报警邮件
    k8s 应用程序获取真实来源ip
    yolov5 安装尝试
    安装pygrib
    ubuntu编译ecodes
    python mpi实验
    mint install gaussian 16
    flask 使用工程外的static文件位置
  • 原文地址:https://www.cnblogs.com/5iedu/p/7077025.html
Copyright © 2020-2023  润新知