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

如何在类成员协程中安全访问this指针?

用C++标准库解决协程中对象提前销毁的问题

要避免协程访问已销毁对象的未定义行为,核心是让协程弱引用对象,在需要访问成员前先确认对象是否存活。借助C++标准库的std::weak_ptr和std::enable_shared_from_this就能实现,具体方案如下:

步骤1:让类继承std::enable_shared_from_this

通过继承这个模板类,对象可以安全获取自身的弱引用,避免手动创建引用导致的计数错误。

步骤2:在协程中持有弱引用并验证对象存活

协程启动时先捕获自身的弱引用,挂起恢复后尝试将弱引用升级为强引用:

  • 升级成功:对象仍存活,安全访问成员变量
  • 升级失败:对象已销毁,执行错误处理逻辑

修改后的完整代码

#include <iostream>
#include <memory>
#include <stdexcept>
#include <chrono>
#include <coroutine>

// 符合C++20协程标准的Task实现(示例用)
template<typename T>
struct Task {
    struct promise_type {
        T value;
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void unhandled_exception() { std::terminate(); }
        Task get_return_object() { return Task{this}; }
        void return_value(T v) { value = std::move(v); }
    };
    promise_type* promise;
    explicit Task(promise_type* p) : promise(p) {}
    T get() { return std::move(promise->value); }
};

struct MyClass : std::enable_shared_from_this<MyClass>
{
    std::string m_value{ "Hello, World!" };

    Task<std::string> RetrieveValueAsync()
    {
        // 获取自身的弱引用,不增加引用计数
        auto weak_this = weak_from_this();
        co_await std::chrono::seconds(5); // 挂起后在线程池恢复

        // 尝试升级为强引用,确认对象是否存活
        if (auto strong_this = weak_this.lock()) {
            co_return strong_this->m_value;
        } else {
            // 对象已销毁,抛出异常或返回默认值
            throw std::runtime_error("对象已在协程完成前被销毁");
        }
    }
};

int main()
{
    try {
        auto instance = std::make_shared<MyClass>();
        auto async_task = instance->RetrieveValueAsync();
        instance = nullptr; // 模拟对象提前销毁

        std::string result = async_task.get();
        std::cout << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "错误:" << e.what() << std::endl;
    }
}

关键细节说明

  • 弱引用不阻止销毁:协程持有std::weak_ptr不会增加对象的引用计数,因此对象可以正常被销毁(比如main中instance = nullptr时)。
  • 线程安全的存活验证:weak_ptr::lock()是线程安全的操作,能可靠判断对象是否还存在,避免悬空指针访问。
  • 错误处理灵活:对象销毁时可以选择抛出异常、返回默认值,或者根据业务需求执行其他逻辑,完全替代C++/WinRT中弱引用的作用。

内容的提问来源于stack exchange,提问作者Tom Huntington

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 00:13:17