C++ 中的 enable_shared_from_this 详解

# C++ 中的 `enable_shared_from_this` 详解

`enable_shared_from_this` 是 C++ 标准库中的一个模板类,用于解决在类的成员函数中需要获取指向自身的 `shared_ptr` 的问题。

## 基本概念

当一个对象由 `shared_ptr` 管理时,如果你想在对象的成员函数中获得一个指向自身的 `shared_ptr`,直接使用 `this` 创建新的 `shared_ptr` 会导致多个不相关的 `shared_ptr` 管理同一个对象,从而造成重复释放的问题。

`enable_shared_from_this` 提供了安全的解决方案。

## 基本用法

```cpp
#include <memory>
#include <iostream>

class MyClass : public std::enable_shared_from_this<MyClass> {
public:
std::shared_ptr<MyClass> getShared() {
return shared_from_this();  // 安全地获取 shared_ptr
}

void doSomething() {
std::cout << "Doing something..." << std::endl;
}
};

int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();

// 安全地获取 shared_ptr
std::shared_ptr<MyClass> ptr2 = ptr1->getShared();

std::cout << "ptr1 use_count: " << ptr1.use_count() << std::endl;  // 输出 2
std::cout << "ptr2 use_count: " << ptr2.use_count() << std::endl;  // 输出 2

ptr2->doSomething();

return 0;
}
```

## 使用注意事项

1. **必须在对象已被 shared_ptr 管理时使用**:
```cpp
// 错误用法 - 对象未被 shared_ptr 管理
MyClass obj;
auto ptr = obj.shared_from_this();  // 抛出 std::bad_weak_ptr 异常
```

2. **不能在构造函数中使用**:
```cpp
class MyClass : public std::enable_shared_from_this<MyClass> {
public:
MyClass() {
// 错误 - 此时对象还未被 shared_ptr 管理
auto ptr = shared_from_this();  // 会抛出异常
}
};
```

3. **不能在析构函数中使用**:
```cpp
class MyClass : public std::enable_shared_from_this<MyClass> {
public:
~MyClass() {
// 错误 - 此时 shared_ptr 引用计数可能已经为 0
auto ptr = shared_from_this();  // 未定义行为
}
};
```

## 实际应用场景

1. **异步回调中保持对象存活**:
```cpp
class NetworkService : public std::enable_shared_from_this<NetworkService> {
public:
void startAsyncOperation() {
auto self = shared_from_this();
asyncOperation([self]() {
// 回调中 self 保持对象存活
self->onOperationComplete();
});
}

void onOperationComplete() {
std::cout << "Operation completed" << std::endl;
}
};
```

2. **链式调用**:
```cpp
class Builder : public std::enable_shared_from_this<Builder> {
public:
std::shared_ptr<Builder> step1() {
// 执行步骤1
return shared_from_this();
}

std::shared_ptr<Builder> step2() {
// 执行步骤2
return shared_from_this();
}
};

// 使用
auto builder = std::make_shared<Builder>();
builder->step1()->step2();
```

## 实现原理

`enable_shared_from_this` 内部维护了一个 `weak_ptr`,当对象被 `shared_ptr` 管理时,`shared_ptr` 的构造函数会检测对象是否继承自 `enable_shared_from_this`,如果是,则初始化内部的 `weak_ptr`。

`shared_from_this()` 实际上是通过这个 `weak_ptr` 来创建一个新的 `shared_ptr`。

## 线程安全性

`shared_from_this()` 是线程安全的,但前提是对象的生命周期管理(即所有相关的 `shared_ptr` 操作)也是线程安全的。

## 替代方案

如果你不能或不想继承 `enable_shared_from_this`,可以考虑以下替代方案:

1. **传递 shared_ptr 作为参数**:
```cpp
void MyClass::memberFunction(std::shared_ptr<MyClass> self) {
// 使用 self
}
```

2. **使用 weak_ptr 成员变量**:
```cpp
class MyClass {
std::weak_ptr<MyClass> weak_this;
public:
void setSelf(const std::shared_ptr<MyClass>& self) {
weak_this = self;
}

std::shared_ptr<MyClass> getShared() {
return weak_this.lock();
}
};
```

`enable_shared_from_this` 是一个强大的工具,但需要正确使用以避免潜在的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92640.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92640.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day11 - 浮动

1. 标签之间的空白问题 1.1. 问题重现 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Document</title><style>img {width: 100px;}</style> </head> <body><a…

MetaBit基金会加码投资图灵协议,深化去中心化金融与元宇宙生态合作

2025年7月15日 —— 新加坡MetaBit基金会宣布进一步加大对图灵协议&#xff08;Turing Protocol&#xff09;的战略投资&#xff0c;涵盖其去中心化交易所&#xff08;DEX&#xff09;、聚合交易平台&#xff08;CEX&#xff09;及公链生态的技术与资金支持。双方还将围绕元宇宙…

NWinfo(硬件信息检测工具)v1.4.20绿色免费版,U盘随走随检,结果即刻导出

[软件名称]: NWinfo(硬件信息检测工具)v1.4.20绿色免费版 [软件大小]: 1.4 MB [软件大小]: 夸克网盘 | 迅雷网盘 软件介绍 NWinfo 诞生于给老旧机器做体检的需求&#xff1a;一个单文件、零依赖的 Win32 小程序&#xff0c;却能像放大镜一样把机箱里的故事读出来。它不借助…

Numpy科学计算与数据分析:Numpy高效数据处理与优化

Numpy性能优化 学习目标 本课程将深入探讨如何利用Numpy库的特性来优化Python代码的性能&#xff0c;重点讲解向量化操作、避免Python循环等技术&#xff0c;帮助学员掌握高效的数据处理方法。 相关知识点 Numpy性能优化 学习内容 1 Numpy性能优化 1.1 Numpy数组与Pytho…

鸿蒙HarmonyOS中Axios网络库封装与文件上传功能实现

在开发鸿蒙HarmonyOS应用时&#xff0c;网络请求功能是必不可少的。axios是一个非常流行的基于Promise的HTTP客户端&#xff0c;适用于浏览器和Node.js环境。本文将介绍如何在鸿蒙HarmonyOS中封装axios库&#xff0c;使其能够支持文件上传&#xff0c;并提供额外的配置选项以满…

【AI】从零开始的文本分类模型实战:从数据到部署的全流程指南

目录 引言 一、项目背景与目标 二、环境准备 三、数据获取与探索 3.1 数据获取 3.2 数据探索 四、数据预处理 4.1 文本清洗 4.2 分词 4.3 标签编码 4.4 数据集划分 4.5 特征提取 五、模型构建与训练 5.1 逻辑回归模型 5.2 LSTM 模型 六、模型评估 6.1 逻辑回归…

Rust学习心得---特征对象和泛型区别

区别特性泛型&#xff08;静态分发&#xff09;特征对象&#xff08;动态分发&#xff09;决策时机编译时单态化&#xff08;生成具体类型的代码&#xff09;运行时通过vtable查找方法运行性能零运行时开销&#xff08;直接内联调用&#xff09;有额外开销&#xff08;指针跳转…

ESP32-menuconfig(2) -- Application manager

按顺序来说&#xff0c;第二篇本来应该是Security features&#xff0c;但是这块内容应该到小批量才用的到&#xff0c;而一些爱好者可能永远都不会修改这块&#xff0c;所以先看看更常用Application manager&#xff0c;这部分内容也比较少。 Application managerCONFIG_APP_C…

ArgoCD 与 GitOps:K8S 原生持续部署的实操指南

容器技术的爆发让 Kubernetes&#xff08;K8s&#xff09;成为了「云原生时代的操作系统」—— 它能高效编排成千上万的容器&#xff0c;解决弹性伸缩、资源调度等核心问题。但随着企业应用规模扩大&#xff0c;K8s 的「部署与管理」逐渐暴露新的挑战&#xff1a; 多环境&…

Day36--动态规划--1049. 最后一块石头的重量 II,494. 目标和,474. 一和零

Day36–动态规划–1049. 最后一块石头的重量 II&#xff0c;494. 目标和&#xff0c;474. 一和零 遇到难题&#xff0c;思考超过20分钟没有思路的&#xff0c;要跳过&#xff01;不然时间效率太低了。 **看题解同理&#xff0c;看20分钟看不懂的&#xff0c;也要跳过&#xff0…

前端开发技术深度总结报告

前端开发技术深度总结报告 &#x1f4cb; 项目背景 基于 Vue 3 TypeScript Element Plus 的企业级产品管理系统&#xff0c;重点解决产品表单的数据缓存、页面导航、用户体验等核心问题。&#xfffd;&#xfffd; 遇到的问题及解决方案 1. 浏览器控制台错误处理 问题: 大量第…

Linux 单机部署 Kafka 详细教程(CentOS 7+)

系列博客专栏&#xff1a; SpringBoot与微服务实践系列博客Java互联网高级培训教程 一、环境准备 1. 操作系统要求 Kafka 可以在多种 Linux 发行版上运行&#xff0c;本文以 CentOS 7 为例&#xff0c;其他发行版步骤类似&#xff0c;只需调整包管理命令。 2. Java 环境要…

解析工业机器视觉中的飞拍技术

在工业机器视觉的领域&#xff0c;"飞拍"这个术语时常被提起&#xff0c;尤其是在高速检测和动态捕捉的场景中。但你真的了解飞拍是什么吗&#xff1f;它到底如何工作&#xff0c;能为工业应用带来哪些突破性改进呢&#xff1f;让我们一起来解密。1. 飞拍的核心概念 …

[特殊字符]企业游学 | 探秘字节,解锁AI科技新密码

宝子们&#xff0c;想知道全球科技巨头字节跳动的成功秘籍吗&#xff1f;一场企业游学&#xff0c;带你深入字节跳动创新基地&#xff0c;探索AI新科技&#xff0c;揭开规模化增长背后的神秘面纱✨字节跳动&#xff1a;全球经济价值的创造者字节跳动可太牛啦&#xff01;TikTok…

主流大数据框架深度解析:从介绍到选型实战

主流大数据框架深度解析:从介绍到选型实战 在数据驱动的时代,选择合适的大数据处理框架是构建高效、可靠数据平台的关键。 深入剖析 Hadoop MapReduce、Apache Spark、Apache Flink 和 Kafka Streams 四大主流框架,从框架介绍、具体使用场景、优缺点、选择建议到实际案例,…

座舱HMI软件开发架构:核心功能与案例解析

随着智能座舱的持续演进&#xff0c;HMI&#xff08;Human Machine Interface&#xff0c;人与机器交互界面&#xff09;系统已从单一的显示控制器演变为集多屏联动、多模态交互、车载服务集成于一体的智能系统&#xff0c;需要一个多系统、多设备协同运行的复杂架构来支撑。本…

把“思考”塞进 1 KB:我用纯 C 语言给单片机手搓了一个微型 Transformer 推理引擎

标签&#xff1a;TinyML、Transformer、单片机、Cortex-M、量化、KV-Cache、裸机编程 ---- 1. 为什么要在 64 KB SRAM 的 MCU 上跑 Transformer&#xff1f; 2024 年以前&#xff0c;TinyML ≈ CNN CMSIS-NN&#xff0c;做语音唤醒或简单分类就到头了。 但产品同事突然拍脑袋&…

什么是CLI?

什么是CLI&#xff1f;CLI&#xff08;Command Line Interface&#xff09;是命令行界面的缩写&#xff0c;是一种通过文本命令与计算机程序交互的方式。通俗比喻CLI就像是一个"智能助手"&#xff1a;你输入命令&#xff0c;它执行任务就像和机器人对话一样&#xff…

mysql基本sql语句大全

十分想念顺店杂可。。。以下是 MySQL 中常用的基本 SQL 语句大全&#xff0c;按功能分类整理&#xff0c;包含语法和示例&#xff0c;方便参考使用&#xff1a;一、数据库操作&#xff08;DDL&#xff09;用于创建、删除、切换数据库。创建数据库-- 基本语法 CREATE DATABASE […

构建响应式在线客服聊天系统的前端实践 Vue3+ElementUI + CSS3

构建响应式客服聊天系统的前端实践在当今数字化时代&#xff0c;客服系统已成为企业与客户沟通的重要桥梁。一个优秀的在线客服系统不仅需要功能完善&#xff0c;还需要在各种设备上都能提供良好的用户体验。本文将介绍如何构建一个响应式的客服聊天界面&#xff0c;确保在桌面…