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

如何向C++协程传递值?可行方案及示例问询

调用者向C++协程传递值的方法解答

首先明确:你无法直接在调用者中获取协程内部创建的MyAwaiter对象——因为co_await MyAwaiter{false}创建的是协程栈上的局部临时对象,调用者没有权限访问协程栈的私有内存,协程也没有暴露该对象的引用接口。

下面提供两种可行的传值方案,附最小可运行示例:


方案一:通过Promise对象传递数据

Promise是协程与调用者之间的标准交互桥梁,我们可以在promise中添加数据存储成员,调用者修改promise的数据,协程从promise中读取。

示例代码

#include <coroutine>
#include <iostream>
#include <string>

struct ReturnObject {
    struct promise_type {
        // 存储调用者传递给协程的数据
        std::string input_data_;
        // 标记是否有新数据待读取
        bool has_new_data_ = false;

        ReturnObject get_return_object() {
            return ReturnObject{
                .h_ = std::coroutine_handle<promise_type>::from_promise(*this)
            };
        }

        // 初始挂起,让调用者有机会先设置数据
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void unhandled_exception() {}
    };

    std::coroutine_handle<promise_type> h_;
    operator std::coroutine_handle<promise_type>() const { return h_; }
};

// 自定义Awaiter,从Promise读取数据
struct DataAwaiter {
    ReturnObject::promise_type& promise_;

    bool await_ready() const noexcept {
        // 无新数据时挂起,等待调用者触发
        return promise_.has_new_data_;
    }

    void await_suspend(std::coroutine_handle<>) const noexcept {}

    std::string await_resume() noexcept {
        // 返回数据并重置标记
        promise_.has_new_data_ = false;
        return promise_.input_data_;
    }
};

ReturnObject counter() {
    for (unsigned i = 0;; ++i) {
        std::cout << "协程迭代: i = " << i << std::endl;
        // 通过co_promise获取当前协程的promise对象
        std::string ret = co_await DataAwaiter{co_promise};
        std::cout << "协程收到数据: " << ret << std::endl;
    }
}

int main() {
    auto h = counter();
    auto& promise = h.promise();

    for (int i = 0; i < 3; ++i) {
        std::cout << "\n调用者准备传递数据" << std::endl;
        // 设置要传递给协程的数据
        promise.input_data_ = "来自调用者的消息 " + std::to_string(i+1);
        promise.has_new_data_ = true;
        // 恢复协程执行
        h();
    }
    h.destroy();
}

方案二:让Awaiter持有外部共享数据源

将Awaiter设计为引用外部可访问的共享数据结构,调用者修改该结构,协程通过Awaiter读取数据。

示例代码

#include <coroutine>
#include <iostream>
#include <string>
#include <memory>

// 共享数据结构,用于调用者和协程之间传递数据
struct SharedData {
    std::string value;
    bool ready = false;
};

struct ReturnObject {
    struct promise_type {
        ReturnObject get_return_object() {
            return ReturnObject{
                .h_ = std::coroutine_handle<promise_type>::from_promise(*this)
            };
        }

        std::suspend_always initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void unhandled_exception() {}
    };

    std::coroutine_handle<promise_type> h_;
    operator std::coroutine_handle<promise_type>() const { return h_; }
};

// 关联共享数据的Awaiter
struct SharedAwaiter {
    std::shared_ptr<SharedData> data_;

    bool await_ready() const noexcept {
        return data_->ready;
    }

    void await_suspend(std::coroutine_handle<>) const noexcept {}

    std::string await_resume() noexcept {
        data_->ready = false;
        return data_->value;
    }
};

ReturnObject counter(std::shared_ptr<SharedData> shared_data) {
    for (unsigned i = 0;; ++i) {
        std::cout << "协程迭代: i = " << i << std::endl;
        std::string ret = co_await SharedAwaiter{shared_data};
        std::cout << "协程收到数据: " << ret << std::endl;
    }
}

int main() {
    auto shared_data = std::make_shared<SharedData>();
    auto h = counter(shared_data);

    for (int i = 0; i < 3; ++i) {
        std::cout << "\n调用者准备传递数据" << std::endl;
        shared_data->value = "共享数据消息 " + std::to_string(i+1);
        shared_data->ready = true;
        // 恢复协程执行
        h();
    }
    h.destroy();
}

总结

  • 你最初的思路(修改awaiter内部值传值)的核心问题是无法访问协程内部的局部awaiter对象,但通过让awaiter关联外部共享数据(方案二),可以实现类似逻辑。
  • 方案一(通过Promise)是C++协程的常规传值方式,因为Promise本身就是为协程与调用者交互设计的标准入口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:33:22