std::async默认策略为延迟或异步执行,需显式指定std::launch::async才强制开线程;future.get()仅能调用一次且会消费对象,多次调用抛异常;支持移动不支持拷贝,共享结果应使用shared_future。

std::async 启动异步任务时,launch策略决定是否真并发
不指定 launch 策略或只写 std::async([]{...}),默认行为是 std::launch::deferred | std::launch::async —— 编译器可自由选择延迟执行(调用 get() 时才运行)或真正异步启动。这常导致“以为开了线程,其实没开”的误判。
- 要强制立即启动新线程,必须显式传入
std::launch::async - 若想确保延迟求值(比如仅当需要结果时才计算),用
std::launch::deferred - 混合策略下,
future.wait_for(...)对deferred任务永远返回std::future_status::deferred,不会超时等待
std::future.get() 只能调用一次,且会阻塞直到就绪
get() 不仅取值,还会“消费” future —— 调用后该 std::future 对象进入无效状态,再次调用 get() 会抛出 std::future_error(错误码为 std::future_errc::no_state)。
- 若需多次访问结果,应先用
get()取出值并保存到变量,而非反复调用 - 想非阻塞检查是否完成,用
wait_for(std::chrono::seconds(0)) == std::future_status::ready - 对
deferred任务,get()会同步执行函数体,不启新线程,也不释放调用线程
std::future 不支持拷贝,移动后原对象失效
std::future 是可移动、不可拷贝类型。把一个 future 赋给另一个变量(如 f2 = std::move(f1))后,f1 变成空状态,再对其调用 get() 或 valid() 会出错。
- 传递
future给函数时,通常按值接收(靠移动语义),或用std::shared_future实现多处读取 - 若需共享结果(比如多个线程都等同一个异步结果),改用
std::shared_future:它支持拷贝,且所有副本共用同一状态 - 从
std::future创建shared_future需显式调用.share(),之后原future失效
异常传播:async 中抛出的异常会被捕获并存入 future
在 std::async 的 lambda 或函数中 throw 异常,不会导致程序终止,而是被封装进 future 内部。调用 get() 时才会重新抛出该异常。
立即学习“C++免费学习笔记(深入)”;
- 这意味着你必须在
get()处理异常,否则未捕获的异常会在get()调用点崩溃 - 可用
future.wait_for(...)+valid()+get()组合实现带超时的异常安全获取 - 注意:如果异步函数未抛异常,但
get()报std::future_error,大概率是 future 已被移动或已调用过get()
async 启动的任务,其线程在 future 析构且未 get() 时可能被阻塞等待 —— 这个隐式同步点容易被忽略。











