当前位置: 首页 > 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;最大熵代表了…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...