【數據結構】28_再論智能指針 (下)

課程目標

完成 SharedPointer 類的具體實現

image.png

SharedPointer 設計要點

  • 類模板ios

    • 經過計數機制( 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 支持多個對象同時指向同一片堆空間;所以,必須支持比較操做。this

編程實驗:智能指針的新成員

文件:SharedPointrt.hspa

#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 最大程度的模擬了智能指針的行爲
  • 計數機制確保多個智能合法的指向同一片堆空間
  • 智能指針智能用於指向堆空間中的內存
  • 不一樣類型的智能指針不要混合使用
  • 堆對象的生命週期由智能指針進行管理
思考
在 DTLib 內部是否須要使用智能指針?爲何?

以上內容整理於狄泰軟件學院系列課程,請你們保護原創!code

相關文章
相關標籤/搜索