新闻中心

c++中的std::enable_shared_from_this有什么陷阱_c++ enable_shared_from_this常见误区

2025-11-22
浏览次数:
返回列表
必须确保对象已被shared_ptr管理且不在构造或析构中才能安全调用shared_from_this(),否则导致未定义行为或崩溃。

c++中的std::enable_shared_from_this有什么陷阱_c++ enable_shared_from_this常见误区

std::enable_shared_from_this 是 C++ 中用于安全地从对象内部生成 std::shared_ptr 的机制,但它使用不当会带来陷阱。许多开发者误以为只要继承它就能随时调用 shared_from_this(),结果导致未定义行为或运行时崩溃。下面介绍几个常见误区和关键注意事项。

1. 在构造函数中调用 shared_from_this()

这是最常见的陷阱。 即使类继承了 std::enable_shared_from_this,在构造函数中调用 shared_from_this() 会导致未定义行为。

原因在于:对象尚未被 std::shared_ptr 完全接管,内部的 weak_ptr 还未被正确初始化。此时调用 shared_from_this() 会抛出 std::bad_weak_ptr 异常(或直接崩溃,取决于实现)。

错误示例:

struct Bad : std::enable_shared_from_this<Bad> {
    Bad() {
        auto ptr = shared_from_this(); // ❌ 未定义行为
    }
};
std::shared_ptr<Bad> p = std::make_shared<Bad>(); // 崩溃!

正确做法: 构造完成后才能使用 shared_from_this(),例如通过静态工厂函数创建对象并返回 shared_ptr

2. 必须通过 shared_ptr 管理对象生命周期

enable_shared_from_this 只在对象已被 shared_ptr 拥有时才有效。

如果你直接在栈上创建对象或用裸指针 new 出来但没有交给 std::shared_ptr,调用 shared_from_this() 同样会失败。

错误示例:

struct NotManaged : std::enable_shared_from_this<NotManaged> {
    void foo() {
        auto p = shared_from_this(); // ❌ 抛出 bad_weak_ptr
    }
};

NotManaged obj;
obj.foo(); // 危险!

解决方法: 确保对象始终由 std::shared_ptr 创建,并且已经完成构造。

3. 多重继承或菱形继承可能引发问题

当类通过多重继承方式间接继承多个 enable_shared_from_this(尤其是不同模板实例),或者存在虚继承时,可能会出现歧义或 weak_ptr 初始化不完整的问题。

虽然标准要求编译器处理单一继承下的正确性,但复杂继承结构可能导致 shared_from_this() 返回错误的指针或失效。

PictoGraphic PictoGraphic

AI驱动的矢量插图库和插图生成平台

PictoGraphic 133 查看详情 PictoGraphic

建议: 尽量避免多重继承中混入多个 enable_shared_from_this。若必须使用,确保设计清晰,优先让基类继承(如果需要),或手动管理 shared_ptr。

4. 子类调用 shared_from_this() 需注意类型转换

当你在派生类中调用 shared_from_this(),返回的是基类的 shared_ptr<base>,前提是基类启用了该功能。

若想获得派生类的 shared_ptr<derived></derived>,需要确保原始的 shared_ptr 是指向派生类对象的,并且你只能通过基类接口获取到它。

通常这不是问题,因为 shared_from_this() 返回的是与原始 shared_ptr 共享所有权的智能指针,类型会被自动推导为当前 this 所属类的 shared_ptr(前提是正确启用)。

但要注意:不要尝试在构造函数中做这种转换。

5. 析构期间调用 shared_from_this() 也不安全

即使对象正在析构,理论上仍处于“被 shared_ptr 拥有”状态,但在析构函数末尾或内部再次调用 shared_from_this() 是危险的。

一些实现允许你在析构函数中调用它(只要还没有释放控制块),但逻辑上这可能导致引用计数延长、资源泄漏甚至死锁。

建议: 避免在析构函数中调用 shared_from_this()。如需延迟操作,考虑使用 weak_ptr 或其他异步机制。

基本上就这些常见坑。只要记住:对象必须已经被 shared_ptr 拥有,且不在构造/析构过程中,才能安全调用 shared_from_this()。否则,行为未定义。设计时推荐配合工厂函数使用,避免直接暴露构造函数。

以上就是c++++中的std::enable_shared_from_this有什么陷阱_c++ enable_shared_from_this常见误区的详细内容,更多请关注其它相关文章!


# 已被  # 佛山市问答营销推广排名  # 安徽贸易网站建设销售  # 厦门seo排名价值大吗  # 新沂网络营销网站推广  # 内江网站建设设计  # 上海文宇建设投诉网站  # 小说优化网站  # 晋中短视频seo服务  # 顺德网站制作建设  # 策划型seo上线时间  # 死锁  #   # 你在  # 多个  # 调试器  # 的是  # 如何使用  # 子类  # 有什么  # red  # 解决方法  # c++ 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: TikTok搜索结果不显示如何解决 TikTok搜索刷新优化方法  Archive of Our Own官网直达 AO3最新可用地址一览  Descript怎样用AI剪辑自动去噪_Descript用AI剪辑自动去噪【自动降噪】  优化 Jest 模拟:强制未实现函数抛出错误以提升测试效率  html网页设计源代码怎么运行_运行html网页设计源代码步骤【指南】  一加 Nord 5 隐私权限异常_一加 Nord 5 系统安全优化  响应式CSS Grid布局:优化网格项在小屏幕下的堆叠与宽度适配  神经网络二分类模型训练异常:高损失与完美验证准确率的排查与修正  不同用户不同价格! 索尼开启账户个性化定价测试  天猫双十一预售商品怎么退款_天猫双十一预售退款操作指南  J*aScript井字棋(Tic-Tac-Toe)核心交互逻辑实现教程  Web Components中自定义开关组件状态同步的常见陷阱与解决方案  支付宝如何管理隐私设置_支付宝隐私保护的配置技巧  初次安装JDK时环境变量如何正确配置_J*A_HOME与PATH设置规则讲解  在J*a项目里如何构建对象之间的契约_接口约束的实际落地  Lar*el如何生成PDF或Excel文件_Lar*el文档导出工具与使用教程  蛙漫官网漫画入口地址_蛙漫在线畅读无广告弹窗  Win10双系统截图高效法 截屏快捷键速记【技巧】  汽车之家官方网站官网入口_汽车之家网页版直接进入  虫虫漫画精品漫画官网_虫虫漫画精品漫画官网进入精品漫画  痛风发作了怎么办? 快速止痛和后期饮食调理  QQ邮箱网页版登录入口 QQ邮箱官方在线使用平台  C++的std::forward_list怎么用_C++ STL中单向链表容器的特点与应用  c++如何使用chrono库处理时间_c++标准库时间与日期操作  Angular中父组件异步更新子组件复选框状态的实践指南  mysql备份恢复性能优化_mysql备份恢复性能优化方法  J*aScript中localStorage数据的获取、清洗与格式化教程  绝地鸭卫平a核爆刀流玩法攻略  火锅吃太多会怎样 火锅吃太多会上火吗  如何在 Excel Online 和 Google 表格中更改日期格式  j*a toString()的覆盖  微信网页版扫码登录入口 微信网页版二维码登录入口  Centos/Linux 系统下安装 composer 的完整步骤  《铁拳8》黑皮辣妹新实机:元气满满的18岁少女!  我的世界mc.js免费游戏直接能玩 我的世界mc.js小游戏免费秒玩入口  谷歌推RCS信息存档功能:公司可监控员工私密信息!  漫蛙网页登录入口 漫蛙漫画官方授权网址  Golang如何处理RPC请求负载均衡_Golang RPC请求负载均衡策略与实践  QQ邮箱登录首页官网地址2026 QQ邮箱官方网页入口  在VS Code中配置和运行Dart程序的完整步骤  漫蛙2网页版漫画入口 漫蛙漫画在线官方登录  动漫共和国防屏蔽稳定域名-动漫共和国官方正版直达通道  Golang如何优化内存分配与垃圾回收_Golang内存管理与GC优化实践  Composer如何在生产环境安全地执行composer update  windows10怎么查看硬盘序列号_windows10硬盘id查询命令  多闪网页版在线观看免费入口_多闪官网访问入口  win11专注助手在哪 Win11免打扰模式设置与自动化规则【指南】  优化MinIO list_objects_v2 操作的性能瓶颈与最佳实践  Composer的 "conflict" 字段有什么用_如何声明不兼容的包以避免依赖冲突  J*a最大堆Heapify方法修复:索引计算与边界条件深度解析 

搜索