0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

std::enable_shared_from_this使用场景

5jek_harmonyos 来源:编程学习总站 作者:写代码的牛顿 2021-08-04 15:35 次阅读

std::enable_shared_from_this使用场景

在很多场合,经常会遇到一种情况,如何安全的获取对象的this指针,一般来说我们不建议直接返回this指针,可以想象下有这么一种情况,返回的this指针保存在外部一个局部/全局变量,当对象已经被析构了。

但是外部变量并不知道指针指向的对象已经被析构了,如果此时外部使用了这个指针就会发生程序奔溃。既要像指针操作对象一样,又能安全的析构对象,很自然就想到,智能指针就很合适!

那么智能指针如何使用呢?现在我们来看一段代码。

#include 《iostream》 #include 《memory》 class Widget{ public: Widget(){ std::cout 《《 “Widget constructor run” 《《 std::endl; } ~Widget(){ std::cout 《《 “Widget destructor run” 《《 std::endl; } std::shared_ptr《Widget》 GetSharedObject(){ return std::shared_ptr《Widget》(this); } }; int main() { std::shared_ptr《Widget》 p(new Widget()); std::shared_ptr《Widget》 q = p-》GetSharedObject(); std::cout 《《 p.use_count() 《《 std::endl; std::cout 《《 q.use_count() 《《 std::endl; return 0; }

编译运行后程序输出如下:

Widget constructor run 1 1 Widget destructor run Widget destructor run 22:06:45: 程序异常结束。

从输出我们可以看到,调用了一次构造函数,却调用了两次析构函数,很明显这是不正确的。而std::enable_shared_from_this正是为了解决这个问题而存在。

02

std::enable_shared_from_this原理和实战

前面我们说使用std::enable_shared_from_this能解决安全获取this指针的问题。在使用之前,我们先来了解下std::enable_shared_from_this是什么?为什么能解决这个问题?std::enable_shared_from_this定义如下:

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; };

std::enable_shared_from_this是模板类,内部有个_Tp类型weak_ptr指针,调用shared_from_this成员函数便可获取到_Tp类型智能指针,从这里可以看出,_Tp类型就是我们的目标类型。

再来看看std::enable_shared_from_this的构造函数都是protected,因此不能直接创建std::enable_from_shared_from_this类的实例变量,只能作为基类使用。因此使用方法如下代码所示:

#include 《iostream》 #include 《memory》 class Widget : public std::enable_shared_from_this《Widget》{ public: Widget(){ std::cout 《《 “Widget constructor run” 《《 std::endl; } ~Widget(){ std::cout 《《 “Widget destructor run” 《《 std::endl; } std::shared_ptr《Widget》 GetSharedObject(){ return shared_from_this(); } }; int main() { std::shared_ptr《Widget》 p(new Widget()); std::shared_ptr《Widget》 q = p-》GetSharedObject(); std::cout 《《 p.use_count() 《《 std::endl; std::cout 《《 q.use_count() 《《 std::endl; return 0; }

这里为什么要创建智能指针p而不是直接创建裸指针p?根本原因在于std::enable_shared_from_this内部的weak_ptr,若只是创建裸指针p,那么p被delete后仍然面对不安全使用内部this指针问题。

因此p只能被定义为智能指针。当p被定义为shared_ptr智能指针后,p指针引用计数是1(weak_ptr不会增加引用计数),再通过shared_from_this获取内部this指针的智能指针,则p的引用计数变为2。

现编译运行输出如下:

Widget constructor run 2 2 Widget destructor run

正确的返回了智能指针,p和q的引用计数都是2,且只调用了一次构造函数和析构函数,不会错误的析构对象多次。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • STD
    STD
    +关注

    关注

    0

    文章

    36

    浏览量

    14345

原文标题:C++里std::enable_shared_from_this是干什么用的?

文章出处:【微信号:harmonyos_developer,微信公众号:harmonyos_developer】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    系统放大器的技术原理和应用场景

    系统放大器是一种重要的电子设备,其技术原理和应用场景都具有一定的专业性和广泛性。以下是对系统放大器的技术原理和应用场景的详细介绍:一、技术原理系统放大器的工作原理基于电子器件的非线性特性,通过控制
    发表于 11-18 14:46

    OTA测试暗箱的技术原理和应用场景

    OTA测试暗箱在无线通信设备的研发与测试中扮演着至关重要的角色。以下是对OTA测试暗箱技术原理和应用场景的详细阐述:一、OTA测试暗箱的技术原理OTA测试暗箱的技术原理主要基于电磁波在封闭空间
    发表于 11-14 14:36

    移动终端测试仪的技术原理和应用场景

    ,确保设备在导航服务中的准确性和可靠性。 应用场景移动终端测试仪的应用场景广泛,涵盖了从研发到生产、从维护到监管的多个环节: 移动维修服务:维修技术人员可以使用便携的综测仪快速对手机进行全面检测
    发表于 11-04 16:01

    实时示波器的技术原理和应用场景

    实时示波器是一种高性能的电子测量仪器,其技术原理和应用场景对于电子工程和通信技术领域具有重要意义。以下是对实时示波器的技术原理和应用场景的详细解释:一、技术原理实时示波器的工作原理基于电子束在荧光屏
    发表于 10-23 14:22

    源测量单元设备的技术原理和应用场景

    源测量单元(SMU)设备是一种集成了精密电源(PPS)和高性能数字万用表(DMM)功能的测试设备。以下是对其技术原理和应用场景的详细解析:一、技术原理 集成功能: SMU在单个仪器中集成了电源
    发表于 10-22 11:10

    太阳膜测试仪的技术原理和应用场景

    太阳膜测试仪的技术原理和应用场景可以详细阐述如下:技术原理太阳膜测试仪的技术原理主要基于光学测量和物理定律。具体来说,它通过模拟太阳光中的各种波长(主要是紫外线、可见光和红外线)的辐射,来检测太阳膜
    发表于 09-29 14:18

    超声波测厚仪的技术原理和应用场景

    超声波测厚仪的技术原理和应用场景详细如下:技术原理超声波测厚仪利用超声波脉冲反射原理来测量材料的厚度。具体工作原理如下: 发射超声波脉冲:测厚仪的探头(也称为换能器)向被测物体发射一束高频超声波脉冲
    发表于 09-27 15:06

    智能IC卡测试设备的技术原理和应用场景

    智能IC卡测试设备的技术原理和应用场景,可以从以下几个方面进行阐述:技术原理智能IC卡测试设备的技术原理主要围绕IC卡的通信和数据处理机制展开。IC卡(包括智能IC卡)通常内置有微电子芯片,该芯片
    发表于 09-26 14:27

    脉冲式线圈测试仪的技术原理和应用场景

    脉冲式线圈测试仪,也被称为数字式匝间绝缘测试仪,其技术原理和应用场景如下:技术原理脉冲式线圈测试仪的技术原理主要基于电磁感应和瞬态波形分析。具体来说,测试仪会对标准线圈绕组和被测试绕组施加相同的脉冲
    发表于 09-18 14:29

    如何对MIL-STD-1553B进行选型

    MIL-STD-1553B产品选型是一个复杂而细致的过程,‌需要综合考虑多个因素以确保所选产品能够满足特定应用场景的需求。一、‌引言MIL-STD-1553B作为一种广泛应用于航空航天领域的数据总线
    的头像 发表于 09-05 17:37 329次阅读
    如何对MIL-<b class='flag-5'>STD</b>-1553B进行选型

    请问risc-v芯片的主要应用场景是哪里?

    如题,我想请教一下risc-v芯片与其他的芯片在应用场景上有哪些不一样?
    发表于 07-30 21:23

    FPGA与MCU的应用场景

    FPGA的应用场景有这些: 快速原型设计 FPGA可以快速配置成多种定制数字电路,允许在不需要昂贵且耗时的制造过程的情况下进行快速部署和修改。 硬件加速 在需要高性能和低延迟的应用中,FPGA的并行
    发表于 07-29 15:45

    STM32待机模式适合用于那些应用场景

    对于查看STM32低功耗模式,共有三种,其中最省电的为待机模式,但是待机模式唤醒后相当于软件复位了,ram及寄存器中的值都复位了,仅仅是备份域的寄存器除外,因此有个疑问,待机模式适合用于那些应用场景
    发表于 05-07 07:46

    NanoEdge AI的技术原理、应用场景及优势

    能耗并提高数据安全性。本文将对 NanoEdge AI 的技术原理、应用场景以及优势进行综述。 1、技术原理 NanoEdge AI 的核心技术包括边缘计算、神经网络压缩和低功耗硬件设计。边缘计算
    发表于 03-12 08:09

    AG32VF-MIPI应用场景

    MIPI接口技术在图像和视频传输中的应用越来越广泛,应用场景也在不断拓展,而不仅限于移动设备。MIPI接口在物联网、智能家居、智能监控、智能电视、智能汽车等领域也得到广泛应用。 MIPI还可
    发表于 01-22 08:56