c++协程需c++20及对应编译选项(g++/clang++/msvc各不同),标准库支持、awaitable驱动封装、io调度、异常与连接生命周期管理缺一不可。

协程支持需要 C++20 且编译器得开对选项
不是所有 C++20 编译器默认启用协程,g++ 需要 -std=c++20 -fcoroutines,clang++ 要加 -std=c++20 -fcoroutines-ts(注意 TS 后缀)。MSVC 2019 16.11+ 支持,但需开启 /std:c++20 /await。漏掉任一标志,co_await 会报错:‘co_await’ is not allowed in a function that does not return a coroutine type。
别急着写 co_await,先确认你的 std::experimental::coroutine_handle 或更推荐的 std::coroutine_handle 能正常包含——如果 #include <coroutine></coroutine> 失败,说明标准库还没跟上编译器,得换工具链或降级用 libco/Boost.ASIO 的协程封装。
数据库驱动必须提供 awaitable 接口
原生 SQLite、MySQL C API 都不支持协程;你不能直接 co_await sqlite3_exec(...)。得自己包装或选支持 await 的驱动:
- SQLite:用
sqlite3_async扩展 + 线程池 +std::suspend_always自定义 awaiter - PostgreSQL:
libpqxx5.4+ 提供connection::exec_params_async,返回awaitable<:vector>></:vector> - 通用方案:用
asio::thread_pool包一层阻塞调用,返回自定义awaitable类型
重点不是“怎么查”,而是“谁来调度 IO”。协程本身不解决阻塞,它只是把回调逻辑扁平化——底层仍需异步 IO 或线程卸载。没这层,协程只是语法糖,还拖慢性能。
手写一个最小可用 awaitable 封装
假设你用线程池执行 MySQL 查询,目标是让 co_await db_query("SELECT id FROM users") 返回 std::vector<:string></:string>:
struct db_awaitable {
std::string sql;
asio::thread_pool& pool;
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle h) {
asio::post(pool, [h, sql = std::move(sql)]() mutable {
auto rows = blocking_mysql_query(sql); // 真实阻塞调用
struct result_t { std::vector<:string> data; };
h.resume(); // 注意:这里没传值,需靠成员变量或外部存储
});
}
std::vector<:string> await_resume() {
return last_result; // 必须线程安全,或改用 promise/future 搭配
}
static thread_local std::vector<:string> last_result;
};</:string></:string></:string>
问题来了:await_resume() 无法直接接收异步结果。更稳妥做法是搭配 std::promise 和 std::future,或者用 asio::awaitable<t></t>(需 ASIO 1.22+)——否则容易出现数据竞争或悬垂引用。
别忽略异常传播和连接生命周期
协程函数里抛异常,co_await 不会自动捕获。如果 blocking_mysql_query 抛 std::runtime_error,它会直接穿透到调用方协程的 promise 的 unhandled_exception(),最终终止整个协程栈。
连接对象(比如 mysql_conn*)不能在协程挂起期间被销毁。常见错误是:
- 把连接作为局部变量声明在协程函数内 → 挂起时析构 →
co_await恢复后访问野指针 - 连接由智能指针管理,但协程跨多个
co_await点,而指针在中间某次 await 后被重置
解决方案只有两个:连接生命周期必须长于协程,或用连接池 + shared_ptr 持有,且确保每个 awaitable 实例都持有强引用。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











