shared_ptr代码实现

shared_ptr代码实现,当前命名为ushared_ptr。
1、定义模板指针T* ptr_和计数指针int* red_count_.
2、空构造。
3、实例化构造,获取真实类型对象,并且计数new为1.
4、创建引用函数,通过参数获取真实类型对象和计数指针对象,并且计数加一。
5、重载operator=函数,通过参数获取真实类型对象和计数指针对象,并且计数加一。
6、重载 operator*和operator-> 实现指针功能。
7、创建获取真实类型对象的函数。
8、创建获取计数的函数。
9、创建析构函数,计数减一,当计数为0时析构真实类型对象。
代码及测试如下:

#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <map>
#include <QDebug>

template <class T>
class ushared_ptr {
private:
    // 保存真实指针
    T* ptr_;
    // 指向引用计数
    int* ref_count_;

public:
    // 空构造。
    ushared_ptr():ref_count_(NULL),ptr_(NULL) {}
    // 构造函数
    ushared_ptr(T *t) {
        ptr_ = t;
        // 初始化引用计数
        ref_count_ = new int(1);
        qWarning()<<"ushared_ptr num"<<*ref_count_;
    }
    // 引用
    ushared_ptr(ushared_ptr& ptr) {
        ptr_ = ptr.ptr_;
        // 引用计数加1
        ref_count_ = ptr.ref_count_;
        (*ref_count_)++;
        qWarning()<<"ushared_ptr num"<<*ref_count_;
    }
    // 重载operator=,然后将新的对象引用次数加一。
    void operator =(ushared_ptr& ptr) {
        ptr_ = ptr.ptr_;
        // 引用计数加1
        ref_count_ = ptr.ref_count_;
        (*ref_count_)++;
        qWarning()<<"ushared_ptr num"<<*ref_count_;
    }
    // 析构
    ~ushared_ptr()
    {
        if (ptr_)
        {
            qWarning()<<"~ushared_ptr num"<<*ref_count_;
            if (--(*ref_count_) == 0)
            {
                qWarning()<<"~ushared_ptr delete"<<*ref_count_;
                delete ref_count_;
                delete ptr_;
            }
            else
                qWarning()<<"~ushared_ptr delete"<<*ref_count_;   
        }
    }
    // 重载 operator*和operator-> 实现指针功能
    T operator *() {return *ptr_;}
    T* operator ->() {return ptr_;}
    // 获取原指针
    T* get() {return ptr_;}
    // 获取计数
    int use_count(){if(ref_count_)return *ref_count_;}
};

class B;
class A
{
public:
    ushared_ptr<B> m_b;
    A(){}
    ~A(){qWarning()<<"~A->B num"<<m_b.use_count();}
};

class B
{
public:
    ushared_ptr<A> m_a;
    B(){}
    ~B(){qWarning()<<"~B->A num"<<m_a.use_count();}
};

void test()
{
    ushared_ptr<A> a(new A);
    ushared_ptr<B> b(new B);
    qWarning()<<"A num"<<a.use_count();
    qWarning()<<"B num"<<b.use_count();
    a->m_b = b;
    //b->m_a = a;
    qWarning()<<"A num"<<a.use_count();
    qWarning()<<"B num"<<b.use_count();
}

int main(int argc, char *argv[])
{
    test();
}

weak_ptr辅助性智能指针,它的作用就是辅助shared_ptr来使用的,帮助shared_ptr解除多个对象都引用对方指针,造成引用成环的问题,它的原理在于它是一种弱引用,它的各种操作不改变shared_ptr的计数大小的。
如以下例子:

class B;
class A
{
public:
    std::shared_ptr<B> m_b;
    A(){}
    ~A(){qWarning()<<"~A->B num"<<m_b.use_count();}
};

class B
{
public:
    std::shared_ptr<A> m_a;
    B(){}
    ~B(){qWarning()<<"~B->A num"<<m_a.use_count();}
};

void test()
{
    std::shared_ptr<A> a(new A);
    std::shared_ptr<B> b(new B);
    qWarning()<<"A num"<<a.use_count();
    qWarning()<<"B num"<<b.use_count();
    a->m_b = b;
    b->m_a = a;
    qWarning()<<"A num"<<a.use_count();
    qWarning()<<"B num"<<b.use_count();
}

int main(int argc, char *argv[])
{
    test();
}

结果

A num 1
B num 1
A num 2
B num 2

初始化和赋值后:A的计数为2,B的计数2。a,b跑出作用域后,AB的智能指针进入析构,A的计数减1为1,B的计数减1为1。两边都为1,因此–(*ref_count_) == 0的条件不成立,都无法进入条件语句内部将A和B的对象delete,所以A和B的析构函数都不会进,也就无法继续后面的操作,会出内存泄露。

当使用了weak_ptr后
如以下:

class B;
class A
{
public:
    std::shared_ptr<B> m_b;
    A(){}
    ~A(){qWarning()<<"~A->B num"<<m_b.use_count();}
};

class B
{
public:
    std::weak_ptr<A> m_a;
    B(){}
    ~B(){qWarning()<<"~B->A num"<<m_a.use_count();}
};

void test()
{
    std::shared_ptr<A> a(new A);
    std::shared_ptr<B> b(new B);
    qWarning()<<"A num"<<a.use_count();
    qWarning()<<"B num"<<b.use_count();
    a->m_b = b;
    b->m_a = a;
    qWarning()<<"A num"<<a.use_count();
    qWarning()<<"B num"<<b.use_count();
}

int main(int argc, char *argv[])
{
    test();
}

结果:

A num 1
B num 1
A num 1
B num 2
~A->B num 1
~B->A num 0

通过结构可以看出,b->m_a = a后A计数仍为1,weak_ptr对shared_ptr的计数不做修改。
初始化和赋值后:A的计数为1,B的计数为2。当a跑出作用域后,A的智能指针进入析构,A的计数减1为0,满足–(*ref_count_) == 0的条件,A会被delete,因此进入A的析构函数,智能指针m_b为A的成员变量,所以它会被析构,然后B的智能指针进入析构函数,B计数减1为1。当b跑出作用域后,B的智能指针进入析构,B的计数减1为0,满足–(*ref_count_) == 0的条件,B会被delete,因此进入B的析构函数,m_a为B的成员变量,它会被析构,此时此刻所有指针都被析构,没有内存泄露。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个简单的 shared_ptr代码实现: ```cpp template<typename T> class shared_ptr { public: shared_ptr() : ptr(nullptr), ref_count(nullptr) {} shared_ptr(T* p) : ptr(p), ref_count(new int(1)) {} shared_ptr(const shared_ptr& other) : ptr(other.ptr), ref_count(other.ref_count) { if (ref_count) { ++(*ref_count); } } shared_ptr& operator=(const shared_ptr& other) { if (this != &other) { release(); ptr = other.ptr; ref_count = other.ref_count; if (ref_count) { ++(*ref_count); } } return *this; } ~shared_ptr() { release(); } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } operator bool() const { return ptr != nullptr; } T* get() const { return ptr; } private: void release() { if (ref_count) { --(*ref_count); if (*ref_count == 0) { delete ptr; delete ref_count; } ptr = nullptr; ref_count = nullptr; } } T* ptr; int* ref_count; }; ``` 在这个实现中,我们使用一个指针 `ptr` 来保存所指向的对象,使用一个指针 `ref_count` 来保存指向该对象的共享指针数量。当一个新的 shared_ptr 对象创建时,我们将 `ref_count` 初始化为 1,表示当前只有一个 shared_ptr 对象指向该对象。当我们拷贝一个 shared_ptr 对象时,我们将 `ref_count` 增加 1,并与原对象共享同一个指针。当一个 shared_ptr 对象被销毁时,我们将 `ref_count` 减 1,如果此时 `ref_count` 的值为 0,表示没有任何 shared_ptr 对象指向该对象了,我们就可以释放该对象的内存和 `ref_count` 的内存了。 此外,我们还实现了 `operator*` 和 `operator->` 来方便访问所指向的对象,实现了 `operator bool` 来判断 shared_ptr 是否为空,实现了 `get` 函数来获取指向的对象的指针。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值