数据结构--另一种智能指针-SharedPointer

上一篇讲了最多只能由一个指针标识堆空间的SmartPointer,本篇讲解另一种智能指针--SharedPointer。

设计要点:

使用类模板实现。

继承自Pointer类

通过计数机制(ref)标识堆空间:被指向时ref++;指向的指针被置空时ref--;当计数变量ref为0时堆空间应该被释放。所以计数变量和堆空间对象是绑定在一起。

由于SharedPointer支持多个对象同时指向一片堆空间,所以需要支持比较操作,所以需要实现比较操作符重载。

由于const对象会使用指针操作符,所以需要重载const版本的(->)和(*)操作符重载。

由于需要重载比较操作符,需要将Pointer类的get函数和isNull函数做成const成员函数。

SharedPointer类声明及完整实现:

 template <typename T>
    class SharedPointer : public Pointer<T>
    {
      protected:
        int* m_ref;//计数变量

    public:
        SharedPointer(T* p = NULL) : m_ref(NULL)
        {
            if(p)
            {
                this->m_ref = static_cast<int*>(malloc(sizeof(int)));
                if(this->m_ref)
                {
                    (*this->m_ref) = 1;//申请空间成功后表示已经有指针指向它,计数变量加1。
                    this->m_pointer = p;
                }
                else//抛出异常
                {
                    THROW_EXCEPTION(NoEnoughMemoryException,"No enough memory to create...");
                }

            }
        }

        SharedPointer(const SharedPointer<T>& obj):Pointer<T>(NULL)//拷贝构造,拷贝成功后计数变量加1
        {
            this->m_ref = obj.m_ref;
            this->m_pointer = obj.m_pointer;
            if(this->m_ref)
                (*this->m_ref)++;
        }

        SharedPointer<T>& operator= (const SharedPointer<T>& obj)//赋值操作符重载,赋值成功后计数变量加1
        {
            if(this != &obj)
            {
                clear();//清理当前指向
                this->m_pointer = obj.m_pointer;//重新赋值
                this->m_ref = obj.m_ref;

                (*this->m_ref)++;
            }
            return *this;
        }
        void clear()//清除当前对象指向的空间,当计数变量为0时释放堆空间和计数变量占用的空间
        {
            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)//const对象只能调用const成员函数
    {
        return !(l == r);
    }


程序分析见注释内容。

SharedPointer最大程度的模拟了原生指针的行为。

计数机制确保多个智能指针合法的指向同一片堆空间。

堆对象的生命周期由智能指针进行管理。

实现了自动管理内存。

使用军规:

只能用来指向堆空间中的单个变量或对象,不能是栈等内存。

不同类型的智能指针对象不能混合使用,SmartPointer对象和SharedPointer对象不能混合使用。

在使用智能指针后不要使用delete释放智能指针指向的堆空间。



测试代码:

class Test : public Object
{

public:
    int value;
    Test():value(0)
    {

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

    Test(int value)
    {
        this->value = value;
        cout << "Test()" << endl;
    }

    ~Test()
    {

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

int main()
{
    SharedPointer<Test> sp = new Test();

    SharedPointer<Test> nsp = NULL;
    nsp = sp;


    cout << sp->value << endl;
    cout << nsp->value << endl;

    nsp->value = 100;


    cout << sp->value << endl;
    cout << nsp->value << endl;

    cout << (sp == nsp) << endl;

    nsp.clear();

    cout << (sp == nsp) << endl;

    cout << endl;
 
    const SharedPointer <Test> pp = new Test(111);

    //(pp->value) = 100;//const对象不能修改成员变量的值,可以加上mutable强制破除只读属性。


    cout << pp->value << endl;

输出结果:

Test()
0
0
100
100
1
0

Test()
111
~Test()
~Test()

请自行对照结果分析原因。


小结:

这两篇内容重新设计了智能指针,使得智能指针在使用中更安全和方便。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值