在C++11及以后的标准中,std::async和std::future组成了一套轻量级的异步任务处理机制。通过它们,我们可以把函数交给系统去后台执行,然后在需要结果的时候再取回来,而不必自己创建和管理std::thread。

一、async与future的基本概念
std::async是一个函数模板,用来启动一个异步任务,它返回一个std::future对象。future代表一个未来的结果,当我们调用它的get成员函数时,如果任务还没完成,调用线程会被阻塞,直到拿到返回值。
1. 最简单的例子
下面演示如何用async启动一个返回整数的任务,并通过future获取结果:
#include <iostream>
#include <future>
int compute() {
// 模拟耗时计算
return 42;
}
int main() {
std::future<int> result = std::async(std::launch::async, compute);
// 此处可以做其他事情
int value = result.get(); // 阻塞直到任务完成并获取返回值
std::cout << "返回值: " << value << std::endl;
return 0;
}
2. 启动策略
std::async的第一个参数可以是启动策略:
- std::launch::async:保证任务在新线程中异步执行。
- std::launch::deferred:延迟执行,直到调用get或wait时才同步运行。
- 不写策略时,由实现自行决定,通常是上面两者的组合。
二、获取带参数的异步任务返回值
async支持把参数传递给任务函数,返回值同样通过future获取。
#include <iostream>
#include <future>
int add(int a, int b) {
return a + b;
}
int main() {
std::future<int> fut = std::async(std::launch::async, add, 10, 20);
std::cout << "10+20=" << fut.get() << std::endl;
return 0;
}
三、异常也会通过future传递
如果异步任务中抛出了异常,调用get时会重新抛出该异常,我们可以用try-catch处理。
#include <iostream>
#include <future>
#include <stdexcept>
int may_throw() {
throw std::runtime_error("任务出错了");
}
int main() {
std::future<int> fut = std::async(may_throw);
try {
fut.get();
} catch (const std::exception& e) {
std::cout << "捕获异常: " << e.what() << std::endl;
}
return 0;
}
四、注意事项
| 要点 | 说明 |
|---|---|
| get只能调用一次 | future的get会转移状态,多次调用会导致std::future_error |
| 析构阻塞 | 未调用get的async返回的future析构时,launch::async策略会阻塞等待任务结束 |
| 共享状态 | 可用std::shared_future让多个地方读取同一结果 |
合理使用std::async和std::future,可以让C++异步任务返回值的获取变得简单直观,减少线程管理负担。