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的成员变量,它会被析构,此时此刻所有指针都被析构,没有内存泄露。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

东方忘忧

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

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

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

打赏作者

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

抵扣说明:

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

余额充值