zoukankan      html  css  js  c++  java
  • 数据结构开发(8):再论智能指针

    0.目录

    1.Pointer与SmartPointer

    2.SharedPointer

    3.小结

    1.Pointer与SmartPointer

    本节目标:

    • 完成 Pointer 类的具体实现
    • 完成 SmartPointer 类的具体实现

    思考

    • 使用智能指针( SmartPointer )替换单链表( LinkList )中的原生指针是否可行?

    问题出在哪里?

    • SmartPointer的设计方案
      1. 指针生命周期结束时主动释放堆空间
      2. 一片堆空间最多只能由一个指针标识
      3. 杜绝指针运算和指针比较

    新的设计方案——是时候创建新的智能指针了!

    Pointer是智能指针的抽象父类( 模板 ):

    • 纯虚析构函数 virtual ~Pointer() = 0;
    • 重载 operator-> ()
    • 重载 operator* ()

    (在StLib中实现Pointer.h和SmartPointer.h)
    Pointer.h

    #ifndef POINTER_H
    #define POINTER_H
    
    #include "Object.h"
    
    namespace StLib
    {
    
    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;
        }
    
        bool isNull()
        {
            return (m_pointer == NULL);
        }
    
        T* get()
        {
            return m_pointer;
        }
    };
    
    }
    
    #endif // POINTER_H
    

    SmartPointer.h

    #ifndef SMARTPOINTER_H
    #define SMARTPOINTER_H
    
    #include "Pointer.h"
    
    namespace StLib
    {
    
    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;
    
                this->m_pointer = obj.m_pointer;
    
                const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
    
                delete p;
            }
    
            return *this;
        }
    
        ~SmartPointer()
        {
            delete this->m_pointer;
        }
    };
    
    }
    
    #endif // SMARTPOINTER_H
    

    main.cpp测试

    #include <iostream>
    #include "SmartPointer.h"
    
    using namespace std;
    using namespace StLib;
    
    class Test : public Object
    {
    public:
        Test()
        {
            cout << "Test()" << endl;
        }
        ~Test()
        {
            cout << "~Test()" << endl;
        }
    };
    
    int main()
    {
        SmartPointer<Test> sp = new Test();
        SmartPointer<Test> spn;
    
        spn = sp;
    
        return 0;
    }
    

    运行结果为:

    Test()
    ~Test()
    

    2.SharedPointer

    思考:

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

    本节目标:

    • 完成 SharedPointer 类的具体实现

    SharedPointer 设计要点:

    • 类模板
      1. 通过计数机制( ref )标识堆内存
        1. 堆内存被指向时:ref++
        2. 指针被置空时:ref--
        3. ref == 0 时:释放堆内存

    计数机制原理剖析:

    SharedPointer 类的声明:

    智能指针的比较:

    • 由于 SharedPointer 支持多个对象同时指向一片堆空间;因此,必须支持比较操作

    (在StLib中实现SharedPointer.h)
    改进Pointer.h

    #ifndef POINTER_H
    #define POINTER_H
    
    #include "Object.h"
    
    namespace StLib
    {
    
    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 // POINTER_H
    

    SharedPointer.h

    #ifndef SHAREDPOINTER_H
    #define SHAREDPOINTER_H
    
    #include <cstdlib>
    #include "Pointer.h"
    #include "Exception.h"
    
    namespace StLib
    {
    
    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(NoEnoughMemoryException, "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();
                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);
    }
    
    }
    
    #endif // SHAREDPOINTER_H
    

    main.cpp测试

    #include <iostream>
    #include "SharedPointer.h"
    
    using namespace std;
    using namespace StLib;
    
    class Test : public Object
    {
    public:
        int value;
    
        Test() : value(0)
        {
            cout << "Test()" << endl;
        }
    
        ~Test()
        {
            cout << "~Test()" << endl;
        }
    };
    
    int main()
    {
        SharedPointer<Test> sp0 = new Test();
        SharedPointer<Test> sp1 = sp0;
        SharedPointer<Test> sp2 = NULL;
    
        sp2 = sp1;
    
        sp2->value = 100;
    
        cout << sp0->value << endl;
        cout << sp1->value << endl;
        cout << sp2->value << endl;
    
        cout << (sp0 == sp2) << endl;
        sp2.clear();
        cout << (sp0 == sp2) << endl;
    
        return 0;
    }
    

    运行结果为:

    Test()
    100
    100
    100
    1
    0
    ~Test()
    

    智能指针的使用军规:

    • 只能用来指向堆空间中的单个变量( 对象 )
    • 不同类型的智能指针对象不能混合使用
    • 不要使用 delete 释放智能指针指向的堆空间

    3.小结

    • SharedPointer 最大程度的模拟了原生指针的行为
    • 计数机制确保多个智能指针合法的指向同一片堆空间
    • 智能指针只能用于指向堆空间中的内存
    • 不同类型的智能指针不要混合使用
    • 堆对象的生命周期由智能指针进行管理
  • 相关阅读:
    【Android】升级ADT 22 引发的错误
    【Android】使用SearchView时软键盘不支持actionSearch的问题
    Mac 升级 OS X 10.8.2 后 VirtualBox 无法启动的问题
    2012年总结
    【Andorid X 项目笔记】魅族照片剪切问题(4)
    【读书笔记】浪潮之巅
    ormlite更改数据库默认位置
    Android实用代码七段(二)
    Android实用代码七段(三)
    【Android】嵌套Fragment无法接收onCreateOptionsMenu事件的问题
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10123896.html
Copyright © 2011-2022 走看看