std::future 必须显式调用 get() 或 wait() 获取结果,否则析构时可能阻塞;get() 唯一取值且同步,调用后不可再调,异常会通过 get() 重抛,悬垂引用导致未定义行为。
std::async 返回的 std::future 必须显式获取结果,否则线程可能被阻塞在析构时(尤其用 std::launch::deferred 时);不调用 get() 或 wait() 就丢弃 future,是常见资源卡死源头。
std::future::get() 是唯一能取值且带同步语义的操作
调用 get() 会:① 阻塞直到异步任务完成;② 移动返回值(对右值引用类型);③ 释放内部共享状态。一旦调用过 get(),再次调用会抛出 std::future_error(错误码为 std::future_errc::no_state)。
常见误用:
- 重复调用
get()—— 程序崩溃 - 只调用
wait()不调用get()—— 值丢了,还可能泄漏线程资源 - 把 future 存在局部作用域却没取值 —— 析构时若任务未完成,
std::launch::async模式下会阻塞等待;std::launch::deferred下则直接在析构线程里同步执行(可能引发死锁)
std::async 启动策略影响 get() 行为和线程生命周期
std::async 默认使用 std::launch::async | std::launch::deferred 组合策略,但实际行为依赖实现。显式指定更可控:
立即学习“C++免费学习笔记(深入)”;
-
std::launch::async:一定新开线程,get()阻塞直到该线程完成 -
std::launch::deferred:不启动新线程,任务延迟到首次调用get()或wait()时,在当前线程同步执行
示例:
auto f1 = std::async(std::launch::deferred, []{ return 42; });
// 此时什么都没发生
f1.get(); // ← 这里才真正执行 lambda,并返回 42
注意:std::launch::deferred 下,wait() 不阻塞也不执行,只有 get() 或 wait_for()/wait_until() 的超时返回后紧接着调用 get() 才触发执行。