std::future::get() 是唯一安全取结果的方式,它阻塞等待任务完成并返回值或重抛异常;重复调用、未检查 valid() 或对已 move 的 future 调用均导致未定义行为或异常。

std::future::get() 是唯一安全取结果的方式
调用 std::future::get() 会阻塞当前线程,直到异步任务完成,并返回结果;一旦调用过 get(),该 std::future 对象就进入“已获取”状态,再次调用会抛出 std::future_error(错误码为 std::future_errc::no_state)。
常见错误是重复调用 get() 或在未检查是否有效时直接调用:
- 没检查
valid()就调用get()→ 触发std::terminate - 把同一个
std::future赋值给多个变量后,在不同地方都调用get()→ 第二次必崩 - 用
std::launch::deferred启动但忘了调用get()→ 任务根本不会执行
std::async 启动方式决定 get() 是否真阻塞
std::async 的启动策略影响执行时机和阻塞行为:
-
std::launch::async:立刻新建线程执行,get()等结果,可能阻塞 -
std::launch::deferred:不立即执行,get()时才同步执行(即“懒加载”),此时get()不是等待,而是直接运行 - 不传策略(默认):由实现决定,可能是任一种,不能假设行为
例如:
auto f = std::async(std::launch::deferred, []{ return 42; });
// 此时函数还没跑
int x = f.get(); // 这里才执行 lambda,并立即返回
异常也会通过 get() 抛出,必须处理
std::future::get() 不仅传递正常返回值,还会把异步任务中未捕获的异常原样重抛出来——这发生在调用方线程,不是原 async 线程。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 如果 async 内部 throw 了,
get()就会 throw 同样的异常(类型不变) - 不加 try/catch 直接调用
get()可能导致程序终止 - 不能用
std::current_exception()在 async 里提前捕获并转存——get()自动处理了
示例:
auto f = std::async([]{
throw std::runtime_error("boom");
});
try {
f.get(); // 这里抛出 runtime_error
} catch (const std::exception& e) {
// 处理它
}
move 语义是转移 future 的唯一合法方式
std::future 不可拷贝,只可移动。想把 future 传给另一个函数或存入容器,必须用 std::move:
- 赋值、函数参数传递、容器 push_back 都需
std::move(f) - 移动后原变量变为
valid() == false,再调用get()会崩溃 - 别对已 move 出去的 future 做任何操作,包括
valid()
典型误用:
auto f = std::async([]{ return 1; });
auto f2 = f; // 编译错误:copy constructor deleted
auto f3 = std::move(f); // OK
f.get(); // UB:f 已失效
最常被忽略的是:异步任务的生命周期绑定在 std::future 上——只要 future 还活着,即使你没调用 get(),后台线程也可能仍在运行(async 启动模式下)。而 deferred 模式下,不调 get() 就永远不执行。这两者行为差异极大,不能靠直觉判断。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










