std::async和std::future是C++11提供的异步任务协作工具,用于后台执行耗时操作并安全获取结果;前者启动任务并返回future,后者通过get/wait等接口访问结果,支持异常传递与超时等待,但仅限单次取值且不可拷贝。

std::async 和 std::future 是 C++11 引入的异步任务协作工具
它们一起帮你把一段耗时操作(比如文件读取、网络请求、复杂计算)扔到后台去跑,主线程不用干等着,还能继续干活;等需要结果时,再安全地取回来。核心思想是:**启动异步任务 + 后续获取结果(或等待完成)**。
std::async:用来“发起一个异步任务”
它像一个启动器,调用后立刻返回一个 std::future 对象,而实际函数会在另一个线程(或延迟到 future.get() 时才执行,取决于 launch 策略)运行。
- 最常用形式:
auto fut = std::async(std::launch::async, []{ return 42; });—— 明确要求新开线程立即执行 - 也可以用
std::launch::deferred,表示“先不执行,等你调 get() 或 wait() 时才同步执行”,类似懒加载 - 默认策略
std::launch::async | std::launch::deferred,由系统决定——但实践中建议显式指定,避免意外同步行为
std::future:代表“尚未就绪的结果”
它是 async 返回的句柄,是你和异步任务之间的唯一联系。它不保存数据本身,而是提供一套安全访问结果的接口:
-
fut.get():阻塞等待,拿到结果(int/void/exception),且只能调一次;第二次调会抛异常 -
fut.wait():只等待完成,不取值,适合 void 类型任务 -
fut.wait_for(...)或fut.wait_until(...):带超时的等待,避免无限卡住 -
fut.valid():检查 future 是否关联有效任务(比如是否被 move 走过)
一个典型用法示例
假设你要并行算两个数的平方和阶乘:
立即学习“C++免费学习笔记(深入)”;
#include#include int square(int x) { return x x; } int factorial(int n) { int res = 1; for (int i = 2; i <= n; ++i) res = i; return res; }
int main() { // 同时启动两个异步任务 auto f1 = std::async(std::launch::async, square, 10); auto f2 = std::async(std::launch::async, factorial, 5);
// 主线程可做其他事……比如打印提示 std::cout zuojiankuohaophpcnzuojiankuohaophpcn "Tasks started, doing something else...\n"; // 等待并取结果(这里会阻塞直到两者都完成) int s = f1.get(); // 100 int f = f2.get(); // 120 std::cout zuojiankuohaophpcnzuojiankuohaophpcn "Square: " zuojiankuohaophpcnzuojiankuohaophpcn s zuojiankuohaophpcnzuojiankuohaophpcn ", Factorial: " zuojiankuohaophpcnzuojiankuohaophpcn f zuojiankuohaophpcnzuojiankuohaophpcn "\n";}
需要注意的几个关键点
- std::future 不支持拷贝,只支持移动——防止多个对象同时尝试 get() 导致未定义行为
- 如果 async 启动的任务抛出异常,异常会被捕获并存储在 future 中;调用 get() 时会重新抛出,方便集中处理错误
- 若不调 get()/wait(),且 future 对象析构时任务仍在运行,析构会阻塞直到任务结束(可能引发隐式等待,需留意)
- 它适合“单次结果”的场景;如需持续通信或流式数据,应考虑 std::thread + 队列、std::promise/std::shared_future 或更高级库(如 folly、libunifex)











