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

标签: c++ 智能指针 指针 auto-ptr shared-ptr
145人阅读 评论(0) 收藏 举报
分类:

之前写了一篇博客是关于智能指针的“发展历史”和内核。
博客可戳 -> 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;
};
查看评论

智能指针的模拟实现

1.引入int main() { int *p = new int; //裸指针 delete p; return 0; }在上面的代码中定义了一个裸指针p,需要我们手动释...
  • Sweet_wen
  • Sweet_wen
  • 2017-07-24 16:25:51
  • 1398

C++智能指针(二):模拟实现三种智能指针

上一篇博客我们简单介绍了智能指针:简单介绍智能指针有关shared_ptr的循环引用问题可以参考博客:weak_ptr–解决shared_ptr循环引用问题auto_ptr模拟实现template c...
  • gebushuaidanhenhuai
  • gebushuaidanhenhuai
  • 2017-08-10 21:47:25
  • 196

模拟指针(一)

模拟指针是用数组元素来模拟链表的一种数据结构。其中,数组的每一个元素都分成了数据域data和指针域link。data的数据类型根据需要而定(即链表要存储的数据的类型),而link为整型,用于指出在链表...
  • victorwhz
  • victorwhz
  • 2014-12-02 14:25:00
  • 1187

栈的应用 数组模拟 (指针)

什么是栈?
  • ACM_e
  • ACM_e
  • 2017-08-08 11:18:25
  • 216

模拟指针

有时候采用一个节点数组以及对该数组进行索引的模拟指针,可以使设计更方便、更高效。...
  • char_c
  • char_c
  • 2017-07-07 09:26:45
  • 127

模拟指针学习笔记(1)-实现模拟指针系统

使用模拟指针有时比使用指针描述更方便间接,甚至更快。下面用数组实现指针的模拟。 创建SimNode类定义结点:template class SimNode { friend SimSpace; pr...
  • qq_23851075
  • qq_23851075
  • 2016-08-10 00:09:37
  • 195

C++智能指针(二)模拟实现三种智能指针

在上一篇博客中提到了Auto_ptr(C++智能指针(一)),下面进行模拟实现Auto_ptr 采用类模板实现#include using namespace std; template class...
  • Nou_Camp
  • Nou_Camp
  • 2017-04-15 20:34:40
  • 452

[学习操练]C++智能指针类的简单实现(类模板实现)

在使用指针的过程中,我们有时需要动态的分配指针,在c++中,我们推荐使用new分配内存,delete释放内存。在编写大型程序的时候,有时我们忘记delete分配的内存,或者多次释放分配的内存,这样会造...
  • Emptynest
  • Emptynest
  • 2017-04-19 14:08:31
  • 247

模拟实现智能指针

首先说一下RAII(资源分配及初始化),定义一个类封装资源的分装和释放,在构造函数中完成资源的分配及初始化,析构函数完成资源的清理,是c++中常用的管理资源,避免内存泄漏。实现了自动释放资源。   智...
  • pamelay
  • pamelay
  • 2016-09-07 16:04:23
  • 149

12864<em>模拟指针</em>时钟

12864 stm32 指针式时钟... 举报的资源分: 3 *类型: *详细原因: 取  消 提  交 12864<em>模拟指针</em>时钟 3积分 立即下载 ...
  • 2018年04月01日 00:00
    个人资料
    持之以恒
    等级:
    访问量: 4564
    积分: 287
    排名: 27万+