std::enable_shared_from_this作用:判断异步回调宿主生命周期
创始人
2025-06-01 14:18:42
0

std::enable_shared_from_this作用

应用场景:解决异步回调发生时宿主对象销毁的问题,C++提供了lambda表达式和各种异步函数,std::thread,std::async或者其他框架api都提供了异步回调方法。api::get(url,> { //解析response})
回调回来的时候宿主类对象已经销毁了,但是大多数情况下我们再处理网络结果的时候需要用到宿主类对象的一些数据,这就造成了问题,宿主对象已经销毁了,他的成员数据也一起销毁了,继续调用只会导致无法预期的问题。

有三种应对方法:
(1)宿主类销毁后,切断回调和宿主之前的关系.(C++不提供这样的方法,需要自己设计),自己重新设置回调指针为空,调用回调函数的地方判断回调指针为空后就不调用。
(2)如果回调没有回来,延长宿主对象的生命周期,继承std::enable_shared_from_this可以做到这一点,那就是让lambda捕获宿主对象的shared_ptr指针(share_from_this()),这样在回调回来之前宿主对象不会销毁。但宿主对象的生命周期就依赖于这些回调被调用的时间,有些场景不合适。
(3)最好的方式就是检测对象是否销毁,如果销毁就不调用,如果没有继续执行,同样继承std::enable_shared_from_this可以做到这一点。让回调lambda捕获宿主对象的弱引用指针(weak_from_this()),在回调回来以后,检测weak_ptr是否可用,可用则获取shared_ptr保证宿主生命周期,然后执行其他方法。不可用直接返回。
使用 weak_from_this 有两点需要注意:

  1. weak_from_this() 最好在对象构造时就保存,避免对象被销毁了才weak_from_this(),这时候会触发weak_ptr构造异常
    2.weak_from_this() 返回的 std::weak_ptr 不可作为类成员,因为对象销毁的时候,成员也销毁了,如果这时候访问 std::weak_ptr 肯定会触发异常
    weak_ptr的lock()函数方法的功能是:判断weak_ptr所指向的shared_ptr对象是否存在。若存在,则这个lock方法会返回一个指向该对象的shared_ptr指针;若它所指向的这个shared_ptr对象不存在,则lock()函数会返回一个空的shared_ptr。
#include 
#include 
#include 
#include 
#include class A : public std::enable_shared_from_this
{
public:A() { std::cout << __FUNCTION__ << std::endl; };~A() { std::cout << __FUNCTION__ << std::endl; };void Start(){auto weak = weak_from_this();std::thread t([weak]() { //捕获宿主弱引用指针std::this_thread::sleep_for(std::chrono::seconds(10));auto self = weak.lock();//weak_ptr所指向的shared_ptr对象不存在会返回空指针,否则返回对象指针if (self) //判断宿主是否销毁{self->PrintSelf();}});t.detach();}void PrintSelf(){std::cout << printInfo << std::endl;}
private:std::string printInfo = " its my self.";
};int main()
{{std::shared_ptr ptrA = std::make_shared(); //继承std::enable_shared_from_this类生命周期由shared_ptr托管ptrA->Start();}//ptrA超出作用域,对象销毁。去掉括号即保证ptrA 不被销毁,可打印出printInfoint wait;std::cin >> wait;
}

参考文章:
https://blog.csdn.net/linfengmove/article/details/107065634/

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...