仿照现代 C++ 智能指针实现自己的引用计数「下」

以下内容为本人的烂笔头,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/XIWsV7LabToq_ehzmXj46w

此文上接《仿照现代 C++ 智能指针实现自己的引用计数「上」》,如果你还没阅读上文,欢迎关注我查看更多内容。


生命周期的结束

上面提到更换托管资源时,还需要解绑自身原有托管的资源。其实当智能指针对象自身的生命周期结束之时,也就是调用释构函数时,也需要解绑自身原有托管的资源,这时的解绑主要做的就是对资源的计数器减 1,并且判断计数器减 1 后是否归零,如果归零就需要释放该资源占用的内存

class SmartPtr
{
    // ...
public:
    ~SmartPtr() {
        if (0 == (-- p_->count_)) {
            delete p_;
        }
    }
};

成员访问

智能指针在托管资源后,资源内部的成员应该能通过智能指针来访问,正如前面介绍资源类时,在资源类内部声明智能指针为友元类。通过智能指针来访问资源类内部成员的形式,应该类似对象的指针访问对象成员,需要通过重写智能指针的成员访问运算符来实现

class SmartPtr
{
    // ...
public:
    Demo* operator->() {
        return p_;
    }
};

operator-> () 是一元右缀操作符,重写了类成员访问运算符,返回被托管的资源指针。

当智能指针对象调用该操作符时,比如 p 被声明为智能指针实例对象,被托管的资源所属类包含成员 m,那么 p->m 会被编译器解析成 ((p.operator->)->m

获取资源引用

一般通过对象指针获取对象引用时,是通过 * 运算符。类似地,需要获取被托管资源对象的引用,可以重写 * 运算符实现

class SmartPtr
{
    // ...
public:
    Demo& operator*() {
        return *p_;
    }
};

避免暴露裸指针

一般不推荐直接调用资源类的裸指针,尽量避免重写智能指针的操作符以返回被托管资源的指针,因为暴露的裸指针会被意外地使用而破坏引用计数的机制,最终破坏实现内存安全的努力。

而上面在设计资源类时,仍然依赖使用 new 操作符创建资源实例并返回裸指针,这无疑是一颗定时炸弹。为了隐藏好裸指针,可以把构造函数声明为 private,并且添加静态成员接口 create() 返回智能指针对象

// .h
class SmartPtr;
class Demo
{
public:
    static SmartPtr create();
private:
    Demo() : count_(0) {};
    unsigned int count_;
    friend class SmartPtr;
};
// ...

// .cpp
SmartPtr Demo::create() {
    return new Demo();
}

为什么接口 Demo::create() 内部直接 return 类 Demo 对象指针而不是 SmartPtr 对象?

因为前面实现类 SmartPtr 时,它的构造函数就有输入 Demo 指针的重载形式。所以接口 Demo::create() 声明返回类型为 SmartPtr 对象时,如果直接返回类 Demo 对象指针,就会隐式调用类 SmartPtr 的对应构造函数创建实例对象并返回。


基于上面的设计结果,当需要在堆里创建 Demo 实例时,内存安全的使用方式就可以是这样子

SmartPtr ptr(Demo::create());

简简单单的思路分析如上,如果各位同学朋友有什么疑问可以向我提,下拉到文章底部有我的联系方式。

最后,非常感激各位朋友的点 「赞」 和点击 「在看」,谢谢!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值