课程目标

完成 SharedPointer 类的具体实现

image.png

SharedPointer 设计要点

  • 类模板

    • 通过计数机制( ref )标识堆内存

      • 堆内存被指向时:ref++
      • 指针被置空时:ref--
      • ref == 0 时:释放堆内存

计数机制原理剖析

image.png

SharedPointer 类的声明

template <typename T>
class SharedPointer : public Pointer<T>
{
public:
    SharedPointer(T *p = NULL);
    SharedPointer(const SharedPointer<T> &obj);
    SharedPointer &operator= (const SharedPointer &obj);
    
    void clear();  // 将当前指针置为空
    
    ~SharedPointer();
    
protected:
    int *m_ref;  // 计数机制成员
};

智能指针的比较

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

编程实验:智能指针的新成员

文件:SharedPointrt.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>
{
public:
    SharedPointer(T *p = nullptr)
    {
        if (p != nullptr)
        {
            m_ref = static_cast<int*>(malloc(sizeof(int)));

            if (m_ref)
            {
                this->m_pointer = p;

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

    }

    SharedPointer(const SharedPointer<T> &obj) : Pointer<T> (nullptr)
    {
        assign(obj);
    }

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

            assign(obj);
        }

        return *this;
    }

    void clear()
    {
        int *ref = this->m_ref;
        T *toDel = this->m_pointer;

        this->m_ref = nullptr;
        this->m_pointer = nullptr;

        if (ref)
        {
            --(*ref);

            if (*ref == 0)
            {
                free(ref);
                delete toDel;
            }
        }
    }

    ~SharedPointer()
    {
        clear();
    }

protected:
    int *m_ref = nullptr;

    void assign(const SharedPointer &obj)
    {
        this->m_ref = obj.m_ref;
        this->m_pointer = obj.m_pointer;

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

template <typename T>
bool operator== (const SharedPointer<T> &lhs, const SharedPointer<T> &rhs)
{
    return (lhs.get() == rhs.get());
}

template <typename T>
bool operator!= (const SharedPointer<T> &lhs, const SharedPointer<T> &rhs)
{
    return  !(lhs == rhs);
}


}

#endif // SHAREDPOINTER_H

文件:main.cpp

#include <iostream>
#include "SharedPointer.h"

using namespace std;
using namespace DTLib;

class Test
{
public:
    int value = 0;

    Test()
    {
        cout << "Test()" << endl;
    }

    ~Test()
    {
        cout << "~Test()" << endl;
    }

};

int main()
{
    SharedPointer<Test> sp0(new Test);
    SharedPointer<Test> sp1 = sp0;
    SharedPointer<Test> sp2 = nullptr;

    sp2 = sp1;
    sp2->value = 100;

    cout << sp0->value << endl;
    cout << sp1->value << endl;
    cout << sp2->value << endl;
    cout << (sp0 == sp1) << endl;

    sp2.clear();

    cout << (sp0 == sp2) << endl;

    return 0;
}

输出:

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

智能指针的使用军规

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

小结

  • ShredPointer 最大程度的模拟了智能指针的行为
  • 计数机制确保多个智能合法的指向同一片堆空间
  • 智能指针智能用于指向堆空间中的内存
  • 不同类型的智能指针不要混合使用
  • 堆对象的生命周期由智能指针进行管理

以上内容整理于狄泰软件学院系列课程,请大家保护原创!


TianSong
734 声望138 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧