(C++)智能指针的模拟实现及使用

来源:互联网 发布:问答系统 知乎 编辑:程序博客网 时间:2024/06/07 01:50

之前写了一篇博客是关于智能指针的“发展历史”和内核。
博客可戳 -> http://blog.csdn.net/JS_Evey/article/details/78021568
但其实内容讲的还是有些泛了,不如自己动手理解来得真切。
那今天,就来用自己的方法来实现一下智能指针的功能吧:D

  • 在动手用代码之前,我们先来梳理一下思路:
    1、智能指针并不是真正意义上的指针,而是一个模拟指针功能的类
    2、因为智能指针最重要的功能就是使用引用计数,所以我们在实现的时候要特别注意这一点。
    3、所有的智能指针都会重载operator*和operator->。
    4、智能指针同时也是一个数据类型,一般用模板类来实现。
    5、同时,我们还需要重载赋值运算符,并对引用计数进行相关的改动。
    6、shared_ptr允许多个指针指向同一个对象,unique_ptr/scopede_ptr则是”独占“所指向的对象。

auto_ptr

模拟实现:

template <class T>class AutoPtr{public:    AutoPtr(T* ptr)        :_ptr(ptr)    {}    ~AutoPtr()    {        if (_ptr)        {            delete _ptr;            _ptr = NULL;        }    }    AutoPtr(const AutoPtr<T>& s)        : _ptr(s._ptr)    {        s._ptr = NULL;    }    AutoPtr& operator= (AutoPtr<T>& s)    {        if (s._ptr != _ptr)        {            if (_ptr)                delete _ptr;            _ptr = s._ptr;            s._ptr = NULL;        }        return *this;    }    T* operator->()    {        return _ptr;    }    T& operator*()    {        return *_ptr;           }private:    T* _ptr;};

测试:

int main(){    auto_ptr<string> ps1(new string("Hello, auto_ptr!"));    cout << "The content is: " << *ps1 << endl;    AutoPtr<string> ps2(new string("Hello, AutoPtr!"));    cout << "The content is: " << *ps2 << endl;    getchar();}

运行结果:

这里写图片描述

unique_ptr/scoped_ptr

模拟实现:

template <class A>class ScopedPtr{public:    ScopedPtr(A* ptr)        :_ptr(ptr)    {}    ~ScopedPtr()    {        if (_ptr)        {            delete _ptr;            _ptr = NULL;        }    }    A* operator->()    {        return _ptr;    }    A& operator*()    {        return *_ptr;    }private:    ScopedPtr(const ScopedPtr<A>&s);//禁止使用拷贝构造函数    ScopedPtr& operator=(ScopedPtr<A>& s);//禁止赋值构造private:    A* _ptr;};

shared_ptr

  • 可以认为每个shared-ptr都有一个关联的计数器,通常称其为引用计数。
  • 无论何时,每当拷贝一个shared-ptr之后,计数器都会递增。
  • 而当我们给shared-ptr赋予一个新值或是shared-ptr被销毁时,计数器就会递减。
  • 一旦一个shared-ptr离开其作用域时,计数器就会递减。
  • 当shared-ptr的计数器变为0,它就会自动释放自己所管理的对象。

代码实现:

template<class B>class SharedPtr{public:    SharedPtr(B* s)        :_ptr(s)        , _count(new int(1))    {}    ~SharedPtr()    {        if (--(*_count) == 0)        {            delete _ptr;            _ptr = NULL;            delete _count;            _count = NULL;        }    }    SharedPtr(SharedPtr<B>& s)        :_ptr(s._ptr)        , _count(s._count)    {        (*_count)++;    }    SharedPtr<B>& operator=(ScopedPtr<B>& s)    {        if (_ptr != s._ptr)        {            if (--(*count) == 0)            {                delete _ptr;                _ptr == NULL;                delete _count;                _count == NULL;            }            _ptr(s._ptr);            _count(s._count);            (*count)++:        }        return *this;    }    B& operator*()    {        return *_ptr;    }    B* operator->()    {        return _ptr;    }    int GetCount()    {        return *_count;    }    B* GetPtr()const    {        return _ptr;    }private:    int* _count;//引用计数    B* _ptr;};

测试代码:

int main(){    SharedPtr<string> ps1(new string("Hello, SharedPtr!"));    SharedPtr<string> ps3(ps1);    // 允许复制    SharedPtr<string> ps2 = ps1;   // 允许赋值    cout << "Count is: " << ps1.GetCount() << ", "        << ps2.GetCount() << ", " << ps3.GetCount() << endl;    cout << "ps1 is: " << *ps1 << ", ptr value is: " << ps1.GetPtr() << endl;    cout << "ps2 is: " << *ps2 << ", ptr value is: " << ps2.GetPtr() << endl;    cout << "ps3 is: " << *ps3 << ", ptr value is: " << ps3.GetPtr() << endl;    cout << endl;    shared_ptr<string> ps4(new string("Hello, shared_ptr!"));    shared_ptr<string> ps5(ps4);    // 允许复制    shared_ptr<string> ps6 = ps4;   // 允许赋值    cout << "Count is: " << ps4.use_count() << ", "     << ps5.use_count() << ", " << ps6.use_count() << endl;    cout << "ps1 is: " << *ps4 << ", ptr value is: " << ps4.get() << endl;    cout << "ps2 is: " << *ps5 << ", ptr value is: " << ps5.get() << endl;    cout << "ps3 is: " << *ps6 << ", ptr value is: " << ps6.get() << endl;    cout << endl;    shared_ptr<string> ps7 = move(ps4); // 注意ps1在move之后,就“失效”了,什么都是“0”    cout << "Count is: " << ps4.use_count() << ", "     << ps5.use_count() << ", " << ps6.use_count() << ", " << ps7.use_count() << endl;    cout << "ps4 is: " << ps4.get() << endl;    cout << "ps7 is: " << *ps7 << ", ptr value is: " << ps7.get() << endl;    getchar();    return 0;}

代码实现:

这里写图片描述

weak_ptr

  • weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。
  • 将一个weak_ptr绑定到一个shared_ptr上,不会改变shared_ptr的引用计数。
  • 一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。
  • 即使有weak_ptr指向对象,对象也还是会被释放。

代码实现:

class WeakPtr{public:    WeakPtr()        :_ptr(NULL)    {}    WeakPtr(WeakPtr<C>& s)        :_ptr(s._ptr)    {}    ~WeakPtr()    {        if (_ptr)        {            delete _ptr;            _ptr = NULL;        }    }    C* operator->()    {        return _ptr;    }    C& operator*()    {        return *_ptr;    }private:    C* _ptr;};
原创粉丝点击