当前位置:首页 > 科技  > 软件

C++智能指针enable_shared_from_this

来源: 责编: 时间:2023-11-17 17:14:06 424观看
导读enable_shared_from_this介绍enable_shared_from_this其实是智能指针中的内容,它的作用就是用于在类的内部,返回一个this的智能指针。对于enable_shared_from_this,初学者可能不明白它的使用场景和使用的必要性,可能有得

DJN28资讯网——每日最新资讯28at.com

enable_shared_from_this介绍

enable_shared_from_this其实是智能指针中的内容,它的作用就是用于在类的内部,返回一个this的智能指针。DJN28资讯网——每日最新资讯28at.com

对于enable_shared_from_this,初学者可能不明白它的使用场景和使用的必要性,可能有得童鞋们会问既然有了this这个指向自己的指针, 为什么还需要enable_shared_from_this这个东西呢,直接用this代替不就好了吗?DJN28资讯网——每日最新资讯28at.com

我们来看看以下代码例子,如果先不运行,你能看出什么问题吗?DJN28资讯网——每日最新资讯28at.com

#include <iostream>class Person{public:    Person() = default;    ~Person(){    };    std::shared_ptr<Person> getPtr(){        return std::shared_ptr<Person>(this);    }};int main() {    std::shared_ptr<Person> person = std::make_shared<Person>();    std::shared_ptr<Person> person1 = person->getPtr();    std::cout << "person.use_count() = " << person.use_count() << std::endl;    std::cout << "person1.use_count() = " << person1.use_count() << std::endl;    return 0;}

以上代码运行崩溃报错了,这是为什么呢?DJN28资讯网——每日最新资讯28at.com

DJN28资讯网——每日最新资讯28at.com

崩溃信息DJN28资讯网——每日最新资讯28at.com

这是因为只有一个Person的指针,但是却被两个智能指针shared_ptr持有,而它们的引用计数都是1,因此当main函数运行完毕后两个智能指针释放时都对同一个Person指针进行释放导致的崩溃。DJN28资讯网——每日最新资讯28at.com

如果我们能让两个智能指针shared_ptr共享同一个引用计数,那么这个崩溃问题就迎刃而解了。而通过让Person继承基类enable_shared_from_this,然后在函数getPtr中 调用基类的shared_from_this就能返回一个this的智能指针,这样即可实现让多个智能指针共享同一个引用计数,而达到销毁时只释放一次的目的。这就是enable_shared_from_this存在的必要性, 这也是this无法替代的功能点。DJN28资讯网——每日最新资讯28at.com

如下是实例代码:DJN28资讯网——每日最新资讯28at.com

#include <iostream>class Person:public std::enable_shared_from_this<Person>{public:    Person() = default;    ~Person(){    };    std::shared_ptr<Person> getPtr(){        return shared_from_this();    }};int main() {    std::shared_ptr<Person> person = std::make_shared<Person>();    std::shared_ptr<Person> person1 = person->getPtr();    std::cout << "person.use_count() = " << person.use_count() << std::endl;    std::cout << "person1.use_count() = " << person1.use_count() << std::endl;    return 0;}

通过运行调试打印,我们可以看到这person和person1这两个智能指针的引用计数都变为了2,这是正确的。DJN28资讯网——每日最新资讯28at.com

DJN28资讯网——每日最新资讯28at.com

通过两个实例代码的对比,我们可以发现问题的根源所在就是我们在返回this的智能指针时,直接调用std::shared_ptr构造函数传入裸指针的方式构造一个智能指针, 而在之前的介绍中我们提到过使用智能指针shared_ptr时尽量使用std::make_shared进行智能指针的构造,避免直接调用std::shared_ptr构造函数传入裸指针的方式进行构造。DJN28资讯网——每日最新资讯28at.com

更多关于enable_shared_from_this的实践对比可以参照官网学习:https://en.cppreference.com/w/cpp/memory/enable_shared_from_thisDJN28资讯网——每日最新资讯28at.com

enable_shared_from_this的实现

我们通过源码的方式来分析下enable_shared_from_this的实现原理,enable_shared_from_this的源码非常简短:DJN28资讯网——每日最新资讯28at.com

template<class _Tp>class _LIBCPP_TEMPLATE_VIS enable_shared_from_this{    mutable weak_ptr<_Tp> __weak_this_;protected:    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR    enable_shared_from_this() _NOEXCEPT {}    _LIBCPP_INLINE_VISIBILITY    enable_shared_from_this(enable_shared_from_this const&) _NOEXCEPT {}    _LIBCPP_INLINE_VISIBILITY    enable_shared_from_this& operator=(enable_shared_from_this const&) _NOEXCEPT        {return *this;}    _LIBCPP_INLINE_VISIBILITY    ~enable_shared_from_this() {}public:    _LIBCPP_INLINE_VISIBILITY    shared_ptr<_Tp> shared_from_this()        {return shared_ptr<_Tp>(__weak_this_);}    _LIBCPP_INLINE_VISIBILITY    shared_ptr<_Tp const> shared_from_this() const        {return shared_ptr<const _Tp>(__weak_this_);}#if _LIBCPP_STD_VER > 14    _LIBCPP_INLINE_VISIBILITY    weak_ptr<_Tp> weak_from_this() _NOEXCEPT       { return __weak_this_; }    _LIBCPP_INLINE_VISIBILITY    weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT        { return __weak_this_; }#endif // _LIBCPP_STD_VER > 14    template <class _Up> friend class shared_ptr;};

通过源码我们可以发现这是一个模版类,将自身类型以模版参数的形式传入到父类,这是典型的CRTP应用,关于CRTP之前我们已经介绍过了,这里不再累赘。感兴趣的童鞋们可以参考之前的博文:DJN28资讯网——每日最新资讯28at.com

C++之CRTP的使用

enable_shared_from_this对外只提供了一个weak_from_this公共方法,其内部通过以为弱引用的智能指针weak_ptr构造了一个shared_ptr,这里并没有什么问题, 问题这个弱引用的智能指针__weak_this_它是在哪里初始化的呢?我们通shared_ptr的构造函数可以发现,如果传入的weak_ptr没有初始化的话是会抛出异常崩溃的。DJN28资讯网——每日最新资讯28at.com

其实成员变量__weak_this_的初始化是在类的外部进行初始化的,它的奥秘就是源码的倒数第二行template ();改为不使用智能指针, 而使用裸指针的方式,修改为 auto person = new Person;,同时注释掉第16行再运行是会崩溃的,这就是因为__weak_this_没有进行初始化的原因。DJN28资讯网——每日最新资讯28at.com

DJN28资讯网——每日最新资讯28at.com

崩溃信息DJN28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-27970-0.htmlC++智能指针enable_shared_from_this

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Python系列:如何提高python程序代码的健壮性

下一篇: C++中的低级内存操作

标签:
  • 热门焦点
  • 一加Ace2 Pro官宣:普及16G内存 引领24G

    一加官方今天继续为本月发布的新机一加Ace2 Pro带来预热,公布了内存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引领,还有呢?#一加Ace2Pro#,2023 年 8 月,敬请期待。”同时
  • K60至尊版狂暴引擎2.0加持:超177万跑分斩获性能第一

    Redmi的后性能时代战略发布会今天下午如期举办,在本次发布会上,Redmi公布了多项关于和联发科的深度合作,以及新机K60 Ultra在软件和硬件方面的特性,例如:“K60 至尊版,双芯旗舰
  • 俄罗斯:将审查iPhone等外国公司设备 保数据安全

    iPhone和特斯拉都属于在各自领域领头羊的品牌,推出的产品也也都是数一数二的,但对于一些国家而言,它们的产品可靠性和安全性还是在限制范围内。近日,俄罗斯联邦通信、信息技术
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • 帅气纯真少年!日本最帅初中生选美冠军出炉

    日本第一帅哥初一生选美大赛冠军现已正式出炉,冠军是来自千叶县的宗田悠良。日本一直热衷于各种选美大赛,从&ldquo;最美JK&rdquo;起到&ldquo;最美女星&r
  • 服务存储设计模式:Cache-Aside模式

    Cache-Aside模式一种常用的缓存方式,通常是把数据从主存储加载到KV缓存中,加速后续的访问。在存在重复度的场景,Cache-Aside可以提升服务性能,降低底层存储的压力,缺点是缓存和底
  • 多线程开发带来的问题与解决方法

    使用多线程主要会带来以下几个问题:(一)线程安全问题  线程安全问题指的是在某一线程从开始访问到结束访问某一数据期间,该数据被其他的线程所修改,那么对于当前线程而言,该线程
  • 2299元起!iQOO Pad明晚首销:性能最强天玑平板

    5月23日,iQOO如期举行了新品发布会,除了首发安卓最强旗舰处理器的iQOO Neo8系列新机外,还在发布会上推出了旗下首款平板电脑——iQOO Pad,其最大的卖点
  • 亲历马斯克血洗Twitter,硅谷的苦日子在后头

    文/刘哲铭  编辑/李薇  马斯克再次挥下裁员大刀。  美国时间11月14日,Twitter约4400名外包员工遭解雇,此次被解雇的员工的主要工作为内容审核等。此前,T
Top