第27课 - 再论智能指针(上)

1、再论智能指针

        思考 

                使用智能指针(SmartPointer)替换单链 

                表(LinkList)中的原生指针是否可行?

LinkList.h

#ifndef LINKLIST_H
#define LINKLIST_H
 
 
#include"List.h"
#include"Exception.h"
#include"SmartPointer.h"
 
 
namespace DTLib
{
 
 
template <typename T>
class LinkList : public List<T>
{
protected:
    struct Node : public Object
    {
        T value;
        SmartPointer<Node> next;
    };
    mutable struct : public Object  //保证内存布局一致
    {
        char reserved[sizeof(T)];   //木有实际作用,仅仅占空间,保证内存布局和Node一样
        SmartPointer<Node> next;
    }m_header;
 
 
    int m_length;
 
 
    SmartPointer<Node> m_current;
    int m_step;
 
 
    Node* position(int i) const
    {
        SmartPointer<Node> ret  = reinterpret_cast<Node*>(&m_header);
 
 
        for(int p=0;p<i;p++)
        {
            ret = ret->next;
        }
 
 
        return ret.get();
    }
 
 
    virtual Node* create()
    {
        return new Node();
    }
    virtual void destroy(Node* pn)
    {
        delete pn;
    }
 
 
public:
    LinkList()
    {
        m_header.next = NULL;
        m_length = 0;
        m_step = 1;
        m_current = NULL;
    }
    bool insert(int i,const T& e)
    {
        bool ret = (0 <= i)&&(i <= m_length);
 
 
        if(ret)
        {
            SmartPointer<Node> node = create();
 
 
            if( node.isNull() )
            {
                SmartPointer<Node> current = position(i);
 
 
                node->value = e;
                node->next = current->next;
                current->next = node;
 
 
                m_length++;
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException,"No memory to insert new element ...");
            }
        }
 
 
        return ret;
    }
    bool insert(const T& e)
    {
        return insert(m_length,e);
    }
    bool remove(int i)
    {
        bool ret = (0 <= i)&&(i < m_length);
 
 
        if(ret)
        {
            SmartPointer<Node> current = position(i);
 
 
            SmartPointer<Node> toDel = current->next;
 
 
            if(m_current.get() == toDel.get())
            {
                m_current = toDel->next;    //游标指向下一个数据元素即可
            }
 
 
            current->next = toDel->next;
 
 
            m_length--;
 
 
          //  destroy(toDel);
 
 
        }
 
 
        return ret;
    }
    bool set(int i,const T& e)
    {
        bool ret = (0 <= i)&&(i < m_length);
 
 
        if(ret)
        {
            position(i)->next->value = e;
        }
 
 
        return ret;
    }
    T get(int i) const
    {
        T ret;
 
 
        if(get(i,ret))
        {
            return ret;
        }
        else
        {
            THROW_EXCEPTION(IndexOutOfBoundsExpception,"Invalid parameter i to get element ...");
        }
 
 
        return ret;
    }
    bool get(int i,T& e) const
    {
        bool ret = (0 <= i)&&(i < m_length);
 
 
        if(ret)
        {
            e = position(i)->next->value;   //position  const 成员函数
        }
 
 
        return ret;
    }
    int find(const T& e) const
    {
        int ret = -1;
        int i = 0;
 
 
        SmartPointer<Node> node = m_header.next;
 
 
        while( node.isNull() )
        {
            if(node->value == e)
            {
                ret = i;
                break;
            }
            else
            {
                node = node->next;
 
 
                i++;
            }
        }
 
 
        return ret;
    }
    int length() const
    {
        return m_length;
    }
 
 
    void clear()
    {
        while( m_header.next.isNull() )
        {
            SmartPointer<Node> toDel = m_header.next;
            m_header.next = toDel->next;
 
 
            m_length--;
 
 
          //  destroy(toDel);
        }
    }
    bool move(int i,int step = 1)
    {
        bool ret = (0 <= i)&&(i < m_length)&&(step > 0);
 
 
        if(ret)
        {
            m_current = position(i)->next;
            m_step = step;
        }
 
 
        return ret;
    }
    bool end()
    {
        return ( m_current.isNull());
    }
    T current()
    {
        if(!end())  //if( m_current != NULL )
        {
            return m_current->value;
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterException,"No value at current position ...");
        }
    }
    bool next()
    {
        int i = 0;
        while((i < m_step) && !end())
        {
            m_current = m_current->next;
            i++;
        }
 
 
        return (i == m_step);
    }
 
 
    ~LinkList()
    {
        clear();    //构造函数析构函数不会发生多态,destroy调用的父类
    }
};
}
#endif // LINKLIST_H
 
 

main.cpp

#include <iostream>
#include"LinkList.h"
 
 
using namespace std;
using namespace DTLib;
 
 
int main()
{
    LinkList<int> list;
 
 
    for(int i=0;i<5;i++)
    {
        list.insert(i);
    }
 
 
    for(list.move(0);!list.end();list.next())
    {
        cout<<list.current()<<endl;
    }
 
 
    return 0;
}
 
 
 
 


    程序崩溃!!!



        问题出在哪里? 

            - SmartPointer的设计方案 

                    指针生命周期结束时主动释放堆空间 

                    —片堆空间最多只能由一个指针标识 

                    杜绝指针运算和指针比较 


         新的设计方案 

                    是时候创建新的智能指针了!

        



            新的设计方案 

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

                            纯虚析构函数virtual ~Pointer() = 0; 

                            重载operator - > () 

                            重载operator * () 

                        


2、编程实验 

智能指针的新方案 Pointer.h     SmartPointer.h

Pointer.h

  1. #ifndef POINTER_H  
  2. #define POINTER_H  
  3.   
  4. #include"Object.h"  
  5.   
  6. namespace DTLib  
  7. {  
  8.   
  9. template <typename T>  
  10. class Pointer : public Object  
  11. {  
  12. protected:  
  13.     T* m_pointer;  
  14. public:  
  15.     Pointer(T* p = NULL)  
  16.     {  
  17.         m_pointer = p;  
  18.     }  
  19.     T* operator -> ()  
  20.     {  
  21.         return m_pointer;  
  22.     }  
  23.     T& operator * ()  
  24.     {  
  25.         return *m_pointer;  
  26.     }  
  27.     bool isNull()  
  28.     {  
  29.         return m_pointer == NULL;  
  30.     }  
  31.     T* get()  
  32.     {  
  33.         return m_pointer;  
  34.     }  
  35.     //只要不实现析构函数,就是抽象类(继承了顶层父类)  
  36. };  
  37.   
  38.   
  39.   
  40. }  
  41.   
  42. #endif // POINTER_H  


SmartPointer.h

  1. #ifndef SMARTPOINTER_H  
  2. #define SMARTPOINTER_H  
  3.   
  4. #include"Pointer.h"  
  5.   
  6. namespace DTLib  
  7. {  
  8.   
  9. template <typename T>  
  10. class SmartPointer : public Pointer<T>  
  11. {  
  12.   
  13. public:  
  14.     SmartPointer(T* p = NULL):Pointer<T>(p)  
  15.     {  
  16.   
  17.     }  
  18.     SmartPointer(const SmartPointer<T>& obj)  
  19.     {  
  20.         this->m_pointer=obj.m_pointer;  
  21.         const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;  
  22.     }  
  23.     SmartPointer& operator= (const SmartPointer<T>& obj)  
  24.     {  
  25.         if(this != &obj)  
  26.         {  
  27.             T* p = this->m_pointer; //异常安全  
  28.   
  29.             this->m_pointer = obj.m_pointer;  
  30.             const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;  
  31.   
  32.             delete p;  
  33.         }  
  34.         return *this;   //支持连续赋值  
  35.     }  
  36.   
  37.     ~SmartPointer() //不是抽象类  
  38.     {  
  39.         delete this->m_pointer;  
  40.     }  
  41.   
  42.   
  43. };  
  44.   
  45. }  
  46.   
  47. #endif // SMARTPOINTER_H  


main.cpp

  1. #include <iostream>  
  2. #include"SmartPointer.h"  
  3.   
  4. using namespace std;  
  5. using namespace DTLib;  
  6.   
  7.   
  8. class Test : public Object  
  9. {  
  10.   
  11. public:  
  12.     Test()  
  13.     {  
  14.         cout<<"Test"<<endl;  
  15.     }  
  16.     ~Test()  
  17.     {  
  18.         cout<<"~Test"<<endl;  
  19.     }  
  20. };  
  21.   
  22. int main()  
  23. {  
  24.     SmartPointer<Test> sp = new Test();  
  25.     SmartPointer<Test> spn;  
  26.   
  27.     spn = sp;  
  28.   
  29.   
  30.   
  31.     return 0;  
  32. }  


                        


To be continued ...

        思考:

                如何实现SharedPointer使得多个智能指针对象可 

                以指向同—片堆内存,同时支持堆内存的自动释放?


            


猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/80245000
今日推荐