掌握C++20的协程:从概念到实践

C++20引入的协程(Coroutines)为异步编程提供了一种更直观、更高效的语法结构。与传统的回调或线程方式相比,协程能够让代码保持同步的写法,却在执行时能够挂起并恢复,从而实现高性能的异步操作。本文将系统讲解协程的核心概念、实现细节以及在实际项目中的应用示例。

1. 协程的基本概念

协程是一种“可挂起的函数”,它可以在执行过程中暂停(co_awaitco_yieldco_return),并在之后某个时刻恢复。C++20标准将协程的实现分为三大角色:

角色 作用 关键词
协程函数 定义协程的入口点 co_awaitco_yieldco_return
协程返回类型 决定协程的状态机 std::futurestd::generator、自定义类型
协程框架 生成协程状态机 std::suspend_alwaysstd::suspend_neverstd::promise

协程的执行模型类似于生成器,但它更通用、更强大。C++的协程本质上是由编译器在编译阶段生成一个状态机类,所有挂起点会被编译成分支,协程内部的变量则变成状态机的成员。

2. 基本语法

// 简单的协程函数,返回 std::generator <int>
std::generator <int> count_to(int n) {
    for (int i = 0; i < n; ++i) {
        co_yield i; // 挂起并返回当前值
    }
}

调用方式:

for (int value : count_to(5)) {
    std::cout << value << ' '; // 输出 0 1 2 3 4
}

协程也可以返回 `std::future

` 或者 `std::promise`,用于异步计算: “`cpp std::future async_add(int a, int b) { co_return a + b; // 立即返回结果 } “` ### 3. 协程与异步 IO 在网络编程或文件 IO 中,协程可以大大简化代码。假设我们使用 Boost.Asio 的异步接口: “`cpp asio::awaitable handle_client(tcp::socket socket) { char data[1024]; std::size_t n = co_await socket.async_read_some(asio::buffer(data), asio::use_awaitable); std::cout class simple_generator { public: struct promise_type { T current_value; simple_generator get_return_object() { return simple_generator{Handle{std::coroutine_handle ::from_promise(*this)}}; } std::suspend_always initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } std::suspend_always yield_value(T value) { current_value = value; return {}; } void return_void() {} void unhandled_exception() { std::terminate(); } }; using Handle = std::coroutine_handle ; simple_generator(Handle h) : coro(h) {} ~simple_generator() { if (coro) coro.destroy(); } T operator*() const { return coro.promise().current_value; } bool next() { if (!coro.done()) coro.resume(); return !coro.done(); } private: Handle coro; }; “` 使用方式与 `std::generator` 类似: “`cpp simple_generator seq(int n) { for (int i = 0; i

发表评论