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

    文章

    39

    浏览量

    14724

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Neway电机方案在电机控制的应用场景

    Neway电机方案在电机控制的应用场景Neway电机方案在电机控制领域的应用场景广泛且效果显著,其核心优势在步进电机、伺服电机控制及CNC机床主轴驱动等场景中得到了充分验证。一、步进电机与伺服电机
    发表于 01-04 10:10

    请问C语言中整形溢出对哪些应用场景影响较大?

    C语言中整形溢出对哪些应用场景影响较大
    发表于 12-24 08:24

    请问MOSFET在电源管理中有哪些应用场景

    MOSFET在电源管理中有哪些应用场景
    发表于 12-23 07:07

    CW32L083系列微控制器有哪些应用场景

    CW32L083系列微控制器有哪些应用场景
    发表于 12-16 07:52

    Switch的应用场景

    Switch的应用场景如下: 调用一到多个函数 设置变量值或者返回一个值 执行一到多个代码片段 如果case标签很多,在switch的前两个使用场景中,使用查找表可以更高效的完成。例如下面的两种
    发表于 12-12 07:28

    动态调整策略的应用场景有哪些?

      动态调整策略的核心价值是 “自适应场景变化、平衡监测精度与资源消耗” ,其应用场景集中在 电网工况波动大、设备资源受限、监测需求多样化 的场景,覆盖电网侧、用户侧、新能源侧等全领域。以下是按
    的头像 发表于 12-11 17:30 1581次阅读

    蓝牙网关是什么?都有哪些功能?应用场景有哪些?

    点,更构建起“设备互联-数据流转-智能管控”的完整链路,成为物联网生态中不可或缺的核心组件。本文将系统解析蓝牙网关的核心价值、技术架构、应用场景、现存挑战及未来趋势,为读者呈现这一关键技术的全貌
    发表于 12-11 15:21

    CW32 SysClk系统时钟的应用场景与切换规则

    。 主要应用场景包括: 1、时钟故障自动切换当检测到当前系统时钟源失效时,可快速安全切换到其它可用时钟源上,提高产品可靠性。 2、功耗管理在待机状态切换 SysClk 的时钟源为低速时钟降低系统功耗,在
    发表于 12-11 07:51

    智能指纹锁CW32系列有哪些应用场景

    智能指纹锁CW32系列有哪些应用场景
    发表于 12-05 06:34

    CPU的几种复位方式适合哪些场景

    1、上电复位 适用场景:系统首次上电或电源以外断电后重新上电时; 2、看门狗复位 适用场景:虚脱程序运行异常,如陷入死循环或长时间无响应时; 3、软件复位 适用场景:软件程序需重启或重新初始化
    发表于 11-27 07:56

    CW32L083有哪些应用场景

    CW32L083有哪些应用场景
    发表于 11-24 07:37

    请问CW32L011有哪些应用场景

    请问CW32L011有哪些应用场景
    发表于 11-17 06:25

    CW32L0系列都有哪些应用场景?有哪些优势?

    目前芯源的低功耗MCU比较火爆,就是CW32L0系列都有哪些应用场景?有哪些优势?
    发表于 11-14 06:03

    Leadway微波产品有哪些应用场景?

    。Leadway微波产品的应用场景如下:5G/6G通信测试毫米波基站与终端设备测试:Leadway的测试级柔性/铠装毫米波线缆(DC-110GHz)支持高频段信号传输与校准,确保通信质量。其低插损特性
    发表于 09-26 09:14

    多端协同主要应用场景介绍

    多端协同 功能描述 多端协同主要包括如下场景: 通过跨设备启动UIAbility和ServiceExtensionAbility组件实现多端协同(无返回数据) 通过跨设备启动UIAbility
    发表于 05-21 07:37