数据结构开发(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 最大程度的模拟了原生指针的行为
  • 计数机制确保多个智能指针合法的指向同一片堆空间
  • 智能指针只能用于指向堆空间中的内存
  • 不同类型的智能指针不要混合使用
  • 堆对象的生命周期由智能指针进行管理
posted @ 2018-12-15 17:02  PyLearn  阅读(354)  评论(0编辑  收藏  举报