c++实现一个简单的智能指针(共享指针)


实现过程

1.指针计数类

class PtrCounter
{
public:
    PtrCounter(): count{1} {}

    void add(){++count;}

    void subtract(){--count;}

    int get() const{return count;}

private:

    std::atomic<int> count;
};

STL提供的共享指针基于引用计数原理,故我们也先定义这样一个指针引用计数类。该类包含三个成员函数,分别为计数加一add()函数,计数减一subtract()函数,和获取计数值 get()函数。还有一个用原子类型封装的私有整型成员变量,初始值为1,它的访问保证不会导致数据的竞争,并且可以用于在不同的线程之间同步内存访问。

2.共享指针模板类

template<typename T>
class SharePtr
{
public:
    SharePtr(T* ptr) : my_ptr{ptr}, my_ref_count{new PtrCounter} {}
    SharePtr() : my_ptr(nullptr),my_ref_count(new PtrCounter){}

    SharePtr(const SharePtr &p)
    {
        this->my_ptr = p.my_ptr;
        this->my_ref_count = p.my_ref_count;
        my_ref_count->add();
    }

    SharePtr& operator = (const SharePtr &p)
    {
        clear();
        this->my_ptr = p.my_ptr;
        this->my_ref_count = p.my_ref_count;
        my_ref_count->add();
        return *this;
    }

    SharePtr(SharePtr &&p)
    {
        this->my_ptr = p.my_ptr;
        this->my_ref_count = p.my_ref_count;
        p.my_ptr = nullptr;
        p.my_ref_count = nullptr;
    }

    SharePtr &operator =(SharePtr &&p)
    {
        clear();
        this->my_ptr = p.my_ptr;
        this->my_ref_count = p.my_ref_count;
        p.my_ptr = nullptr;
        p.my_ref_count = nullptr;
        return *this;
    }
    ~SharePtr(){clear();}

    int use_count() {return my_ref_count->get();}

    T* get() const {return my_ptr;}
    T* operator->() const {return *my_ptr;}
    T& operator*() const {return *my_ptr;}
    operator bool() const {return my_ptr;}

private:
    T* my_ptr;
    PtrCounter* my_ref_count;

    void clear()
    {
        if(my_ref_count)
        {
            my_ref_count->subtract();
            if(my_ref_count->get() == 0)
            {
                if(my_ptr) delete my_ptr;
                delete my_ref_count;
            }
        }
    }
};

接着是共享指针核心类。该类有两个私有成员指针变量分别为指针引用计数类型指针和模板参数类型指针。类重载了两个构造函数,一个传模板参数类型指针参数,一个未带参数,在构造函数里都对成员变量做了初始化。拷贝构造进行浅拷贝并引用计数加一,赋值函数在进行浅拷贝之前会先做一个重要的清除操作,该操作先将指针引用计数减一,并判断指针引用计数是否为0,若是,则delete 掉两个指针成员变量。另外定义了移动拷贝构造函数和移动赋值函数,这两个函数和前两个构造函数和移赋值函数的区别在于是否将模板参数类型指针成员变量置为空。最后是析构函数,做清除操作。

测试

struct A
{
    A() {std::cout<<"A()\n";}
    ~A(){std::cout<<"~A()\n";}
};

void test_sharePtr()
{
    A* a = new A;
    SharePtr<A> ptr(a);
    {
      std::cout<<ptr.use_count()<<std::endl;

      //调用拷贝构造函数
      SharePtr<A> b= ptr;
      std::cout<<b.use_count()<<std::endl;
      std::cout<<ptr.use_count()<<std::endl;

      SharePtr<A> c;
      //调用赋值函数      
      c = ptr;
      std::cout<<c.use_count()<<std::endl;
      std::cout<<ptr.use_count()<<std::endl;

    }
    std::cout<<ptr.use_count()<<std::endl;
}

测试结果:
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值