C++20 引入了协程(Coroutines),这是一种特殊的函数,它可以暂停执行并在之后恢复,而不是像普通函数那样一旦返回就终止。协程的主要特点在于它能保留自身的执行状态,这让异步编程更加简洁和直观。以下是对 C++20 协程的详细介绍:
关键概念
co_await
:这是一个操作符,用于暂停协程的执行,直至等待的异步操作完成。当异步操作完成后,协程会恢复执行。co_yield
:此操作符用于暂停协程的执行,并返回一个值给调用者。协程之后可以继续执行。co_return
:该操作符用于终止协程的执行,并返回一个值给调用者。
示例代码
下面的代码展示了一个简单的 C++20 协程示例:
#include <coroutine>
#include <iostream>
#include <stdexcept>// 生成器类模板
template <typename T>
class Generator {
public:struct promise_type {T current_value; // 当前生成的数值// 协程初始化时直接挂起(惰性执行)std::suspend_always initial_suspend() noexcept { return {}; }// 协程结束时保持挂起以便获取最终结果std::suspend_always final_suspend() noexcept { return {}; }// 协程返回时调用(无返回值)void return_void() noexcept {}// 处理未捕获的异常void unhandled_exception() { throw; }// 生成器构造入口Generator get_return_object() { return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};}// 定义 co_yield 行为std::suspend_always yield_value(T value) {current_value = value;return {};}};// 协程句柄std::coroutine_handle<promise_type> coro_handle;// 构造函数explicit Generator(std::coroutine_handle<promise_type> h) : coro_handle(h) {}// 析构时销毁协程~Generator() { if (coro_handle) coro_handle.destroy(); }// 迭代器支持bool move_next() {if (!coro_handle.done()) {coro_handle.resume();return !coro_handle.done();}return false;}T current() const { return coro_handle.promise().current_value; }// 范围遍历支持struct Iter {Generator& gen;bool operator!=(std::nullptr_t) const { return gen.move_next(); }void operator++() {}T operator*() const { return gen.current(); }};Iter begin() { return Iter{*this}; }std::nullptr_t end() { return nullptr; }
};// 生成整数序列的协程函数
Generator<int> generate_sequence(int start, int end) {for (int i = start; i <= end; ++i) {co_yield i; // 每次生成一个值并挂起}
}int main() {// 生成 1 到 10 的序列auto seq = generate_sequence(1, 10);// 遍历输出for (auto num : seq) {std::cout << num << " ";}// 输出: 1 2 3 4 5 6 7 8 9 10
}
代码解释
Task
结构体:它是协程的返回类型,包含了promise_type
结构体,用于定义协程的行为。coroutineFunction
函数:这是一个协程函数,使用co_await std::suspend_always{}
来暂停协程的执行,然后使用co_return 42
来终止协程并返回值 42。main
函数:调用coroutineFunction
函数获取协程对象,然后调用get
方法获取协程的返回值并输出。
这个示例只是一个简单的演示,在实际应用中,协程通常会用于处理异步 I/O 操作,以提高程序的性能和响应能力。