当前位置: 首页 > news >正文

C++:捕获 shared_from_this()和捕获this的区别

两种方法的主要区别在于对象的生命周期管理以及捕获方式的不同。以下是对两种方法的详细对比:


第一种:捕获 shared_from_this() 的方法

event.subscribe([self = shared_from_this()]() {std::cout << "Event triggered, object is alive." << std::endl;self->onEvent();
});
特点:
  1. 对象生命周期管理

    • 使用 shared_from_this() 捕获当前对象的 std::shared_ptr,保证对象在事件回调执行期间不会被销毁。
    • 即使外部没有对对象的引用,self 持有一个 shared_ptr,延长了对象的生命周期。
    • 适用于需要确保对象在事件发生时仍然有效的场景。
  2. 线程安全性

    • 如果事件回调可能在多线程环境中执行,这种方式可以避免悬空指针的风险。
  3. 对象有效性保障

    • 通过 shared_ptr 持有,可以避免事件触发时对象已被销毁的问题。

第二种:捕获 this 指针的方法

event.subscribe([this]() { std::cout << "Event triggered, object is alive." << std::endl;this->onEvent(); 
});
特点:
  1. 生命周期依赖 this

    • 直接捕获 this 指针,依赖于调用 subscribe 时对象的生命周期。
    • 如果对象在事件触发之前被销毁,则调用 onEvent 会导致未定义行为(悬空指针)。
  2. 效率较高

    • 不需要额外的 shared_ptr 管理,直接捕获 this,开销更低。
    • 适用于生命周期完全受控、确保对象在事件回调中一定有效的场景。
  3. 风险

    • 如果对象在事件触发前已经被销毁,就会导致悬空指针错误,因此适合更受控的环境。

适用场景对比

方法优点缺点适用场景
捕获 shared_from_this()确保对象生命周期,安全性高。可用于异步或多线程环境,避免悬空指针。引入了 shared_ptr,增加了一些开销;要求对象继承 std::enable_shared_from_this异步事件、跨线程回调,或者在事件触发期间需要确保对象存活时。
捕获 this 指针效率高,简单直接,无需 shared_ptr 的额外管理。如果对象生命周期不受控(可能在事件触发前销毁),会导致悬空指针,容易出错。对象生命周期受控的情况下(如事件和对象生命周期严格同步,或者对象销毁前确保事件解绑)。

代码示例

捕获 shared_from_this() 的安全示例:
class Event;
class MyObject : public std::enable_shared_from_this<MyObject> {
public:void onEvent() {std::cout << "Event handled by shared_from_this!" << std::endl;}void subscribeToEvent(Event& event) {event.subscribe([self = shared_from_this()]() {std::cout << "Event triggered, object is alive." << std::endl;self->onEvent();});}
};
捕获 this 的受控示例:
class MyObject {
public:void onEvent() {std::cout << "Event handled by this pointer!" << std::endl;}void subscribeToEvent(Event& event) {event.subscribe([this]() {std::cout << "Event triggered, ensure object is valid." << std::endl;this->onEvent();});}
};

总结:

  • 如果对象生命周期由 std::shared_ptr 管理,建议使用 shared_from_this(),因为它可以确保对象在回调中存活。
  • 如果对象生命周期完全受控,且明确保证事件回调执行时对象一定存活,可以选择效率更高的 捕获 this

相关文章:

C++:捕获 shared_from_this()和捕获this的区别

两种方法的主要区别在于对象的生命周期管理以及捕获方式的不同。以下是对两种方法的详细对比&#xff1a; 第一种&#xff1a;捕获 shared_from_this() 的方法 event.subscribe([self shared_from_this()]() {std::cout << "Event triggered, object is alive.&qu…...

网络协议之TCP

一、定义 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议&#xff0c;由IETF的RFC 793定义。TCP旨在适应支持多网络应用的分层协议层次结构。在因特网协议族&#xff08;Internet p…...

《澳鹏AI全景报告2024》分析最新的数据挑战

华盛顿州柯克兰市&#xff0c;2024 年 10 月 22 日 —— Appen Limited&#xff08;澳大利亚证券交易所代码&#xff1a;APX&#xff09;&#xff0c;一家为人工智能生命周期提供高质量数据的领先供应商&#xff0c;发布了其《2024 年人工智能现状报告》。该报告对美国多个行业…...

【Java每日面试题】—— String、StringBuilder和StringBuffer的区别?

1、String 不可变性:String对象创建后不可变,内容不能被修改,对字符串修改会产生一个新的字符串对象。 线程:线程安全 适用:字符串内容不发生变化或少量字符串操作 String str = "Hello"; str = str + " World"; 2、StringBuffer 不可变性:对…...

【设计模式】【创建型模式(Creational Patterns)】之单例模式

单例模式是一种常用的创建型设计模式&#xff0c;其目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 单例模式的原理 单例模式的核心在于控制类的实例化过程&#xff0c;通常通过以下方式实现&#xff1a; 私有化构造函数&#xff0c;防止外部直接实例化。…...

form表单的使用

模板 <template><el-form :model"formData" ref"form1Ref" :rules"rules"><el-form-item label"手机号" prop"tel"><el-input v-model"formData.tel" /></el-form-item><el-f…...

PDF内容提取,MinerU使用

准备环境 # python 3.10 python3 -m pip install huggingface_hub python3 -m pip install modelscope python3 -m pip install -U magic-pdf[full] --extra-index-url https://wheels.myhloli.com下载需要的模型 import json import osimport requests from huggingface_hub…...

SpringCloud篇(服务网关 - GateWay)

目录 一、简介 二、为什么需要网关 二、gateway快速入门 1. 创建gateway服务&#xff0c;引入依赖 2. 编写启动类 3. 编写基础配置和路由规则 4. 重启测试 5. 网关路由的流程图 6. 总结 三、断言工厂 四、过滤器工厂 1. 路由过滤器的种类 2. 请求头过滤器 3. 默认…...

自动化测试之unittest框架详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 unittest 1、什么是Unittest框架&#xff1f; python自带一种单元测试框架 2、为什么使用UnitTest框架&#xff1f; >批量执行用例 >提供丰富的断…...

Vue3 provide 和 inject的使用

在 Vue 中&#xff0c;provide 和 inject 是 Composition API 的一对功能&#xff0c;用于父子组件之间的依赖注入。它们的作用是让父组件可以向其所有子组件提供数据或方法&#xff0c;而不需要通过逐层传递 props。 1. provide provide 用于父组件中&#xff0c;提供数据或…...

掌握Git分布式版本控制工具:从基础到实践

一、引言 在软件开发过程中&#xff0c;版本控制是不可或缺的一环。Git作为一种分布式版本控制工具&#xff0c;以其高效、灵活的特点&#xff0c;受到了广大开发者的青睐。本文将详细介绍Git的基本概念、工作流程、常用命令&#xff0c;以及在IntelliJ IDEA中的操作方法。 二、…...

AndroidStudio与开发板调试时连接失败或APP闪退的解决方案,涉及SELINUX及获取Root权限

现象 用AndroidStudio打开工程代码,点击运行后,报错: 解决方案 具体原因是尝试运行 su(通常用于获取超级用户权限)时失败了,提示 “Permission denied” 通过 CONFIG_SECURITY_SELINUX 变量控制 SElinux 开启或关闭 在vim /rk3568_android_sdk/device/rockchip/rk…...

VMWARE虚拟交换机的负载平衡算法

一、基于源虚拟端口的路由 虚拟交换机可根据 vSphere 标准交换机或 vSphere Distributed Switch 上的虚拟机端口 ID 选择上行链路。 基于源虚拟端口的路由是 vSphere 标准交换机和 vSphere Distributed Switch 上的默认负载平衡方法。 ESXi主机上运行的每个虚拟机在虚拟交换…...

安卓InputDispatching Timeout ANR 流程

1 ANR的检测逻辑有两个参与者: 观测者A和被观测者B&#xff0c;当然&#xff0c;这两者是不在同一个线程中的。2 A在调用B中的逻辑时&#xff0c;同时在A中保存一个标记F&#xff0c;然后做个延时操作C&#xff0c;延时时间设为T&#xff0c;这一步称为: 埋雷 。3 B中的逻辑如果…...

【Nginx从入门到精通】03 、安装部署-让虚拟机可以联网

文章目录 总结一、配置联网【Minimal 精简版】1.1、查看网络配置1.2、配置ip地址 : 修改配置文件 <font colororange>ifcfg-ens33Stage 1&#xff1a;输入指令Stage 2&#xff1a;修改参数Stage 3&#xff1a;重启网络Stage 4&#xff1a;测试上网 二、配置联网【Everyth…...

java 增强型for循环 详解

Java 增强型 for 循环&#xff08;Enhanced for Loop&#xff09;详解 增强型 for 循环&#xff08;也称为 “for-each” 循环&#xff09;是 Java 从 JDK 5 开始引入的一种便捷循环语法&#xff0c;旨在简化对数组或集合类的迭代操作。 1. 基本语法 语法格式 for (类型 变量…...

浪潮云启操作系统(InLinux) bcache宕机问题分析

前言 本文以一次真实的内核宕机问题为切入点&#xff0c;结合实际操作案例&#xff0c;详细展示了如何利用工具 crash对内核转储&#xff08;kdump&#xff09;进行深入分析和调试的方法。通过对崩溃日志的解读、函数调用栈的梳理、关键地址的定位以及代码逻辑的排查&#xff…...

038集——quadtree(CAD—C#二次开发入门)

效果如下&#xff1a; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using System; using System.Collections.Generic; using System.Linq; using System.T…...

备赛蓝桥杯--算法题目(1)

1. 链表求和 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode *head nullptr, *tail nullptr;int carry 0;while (l1 || l2) {int n1 l1 ? l1->val: 0;int n2 l2 ? l2->val:…...

机器学习100道经典面试题库(二)

机器学习100道经典面试题库&#xff08;31-60&#xff09; 在大规模的语料中&#xff0c;挖掘词的相关性是一个重要的问题。以下哪一个信息不能用于确定两个词的相关性。 A、互信息 B、最大熵 C、卡方检验 D、最大似然比 答案&#xff1a;B 解析&#xff1a;最大熵代表了…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...