You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理对象析构函数中需要有效std::shared_ptr的问题?

问题:确保std::shared_ptr管理的对象在销毁前发送关闭事件的可行方案

我有一个由std::shared_ptr管理的对象,它会发送多种事件,所有事件都包含指向该对象的std::shared_ptr。该对象存在一个关闭状态,系统其他组件需要知晓此状态,对象会通过事件通知进入该状态。对象必须在销毁前告知进入关闭状态,以便其他组件了解它将不再执行任何操作。

最直观的做法是在对象析构函数中发送关闭事件,但在析构函数内无法合理调用shared_from_this()——此时对象的引用计数已经开始递减,调用shared_from_this()会抛出异常或返回无效的shared_ptr。

当前困境

当前析构函数强制要求对象已处于关闭状态,但可选的处理方式都不理想:

  • 在析构函数中抛出异常(强烈不推荐);
  • 调用abort()(目前采用的方式)。

这个对象属于一个库的一部分,即便文档明确要求必须先关闭再销毁,abort()的行为也过于强硬。而且对象很可能在调用关闭方法前就超出作用域,我不希望库的行为这么激进。

尝试过的方案及问题

  • 自定义删除器:给std::shared_ptr传入自定义删除器,但shared_ptr会在shared_from_this()抛出异常后才调用删除器,这和引用计数的生命周期逻辑一致,无法解决问题。
  • 包装类方案:用小型包装类持有对象的std::shared_ptr,对外暴露包装类的shared_ptr而非对象本身。包装类的析构函数负责关闭对象,保证对象的shared_ptr有效,但存在两个问题:
    1. 事件中携带的是shared_ptr<Object>而非shared_ptr<Wrapper>,存在不一致性;
    2. 外界可能复制shared_ptr<Object>,脱离包装类的管控。
  • 原始指针/引用替代shared_ptr:让事件携带对象的原始指针或引用,但事件可能被排入队列并在其他线程处理,会引发悬垂指针等严重问题,同样存在不一致性。
  • 特殊处理关闭事件:比如将关闭事件文档化为可能持有nullptr,或者改用std::weak_ptr。但weak_ptr无法保证对象在事件生命周期内存活,而我需要提供这个保障;如果传入nullptr,事件消费者无法识别是哪个对象发送的关闭通知,实用性很低。
  • 依赖use_count()/unique():C++20中unique()已被移除,use_count()在多线程环境中返回的是近似值(典型实现用memory_order_relaxed加载),无法作为可靠判断依据。

难道只能约定对象必须先关闭再销毁,并保留abort()的强硬处理吗?


内容的提问来源于stack exchange,提问作者Tyler Riddle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 20:03:18