wait()仅阻塞至任务完成而不取值,get()则等待并返回结果且只能调用一次;重复调用或先wait()后get()会抛出std::future_error;get()还会重抛任务中异常。

wait() 和 get() 的区别必须分清
wait() 只阻塞到任务完成,不取结果;get() 既等待又返回值,且只能调用一次。多次调用 get() 会抛出 std::future_error(错误码为 std::future_errc::no_state 或 std::future_errc::future_already_retrieved)。
- 如果只需要同步等待、不关心返回值,用
wait()更轻量 - 如果要取值,直接用
get(),别先wait()再get()—— 这样多此一举,还可能因状态已转移导致异常 -
get()在任务异常结束时会重新抛出原始异常(比如std::runtime_error),需用try/catch包裹
auto f = std::async([]{ return 42; });
// ✅ 正确:一步到位
int x = f.get(); // 等待 + 取值
<p>// ❌ 错误:重复取值
f.wait();
int y = f.get(); // 抛出 future_error</p>
wait_for() 和 wait_until() 用于带超时的等待
wait_for() 接 std::chrono::duration(如 std::chrono::seconds(2)),wait_until() 接绝对时间点(如 std::chrono::steady_clock::now() + 2s)。两者都返回 std::future_status 枚举,常见值是 ready、timeout、deferred。
- 返回
timeout时,get()仍可安全调用(只要 future 仍有有效状态),它会继续阻塞直到就绪 - 不要假设超时后 future 就“失效”了 —— 它只是还没完成,状态依然合法
- 若用
std::launch::deferred启动,wait_for()会立即返回deferred,且get()会同步执行函数体(不新开线程)
auto f = std::async(std::launch::async, []{
std::this_thread::sleep_for(3s);
return "done";
});
if (f.wait_for(1s) == std::future_status::timeout) {
std::cout <h3>shared_future 支持多次 get()</h3><p>普通 <code>std::future</code> 移动后原对象失效,无法共享;而 <code>std::shared_future</code> 可拷贝,多个副本都能独立调用 <code>get()</code> 或 <code>wait()</code>。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 从
std::future创建:调用.share()成员函数,原 future 失效(变成空状态) - 常用于需要多个线程分别等待/取值的场景,比如一个异步计算结果被 UI 线程和日志线程同时消费
- 注意:所有
shared_future副本共享同一内部状态,任一副本调用get()都会触发等待(如果未就绪),但不会互相干扰取值逻辑
auto f = std::async([]{ return 123; });
std::shared_future<int> sf = f.share(); // f now invalid
<p>auto t1 = std::thread([&sf]{ std::cout </p></int>
future 对象销毁时未等待的后果
如果 std::future(非 deferred 模式)在析构前没调用 wait() 或 get(),且对应异步任务仍在运行,程序会调用 std::terminate() —— 这是标准强制行为,不是 bug。
- 原因:避免“遗弃”后台任务导致资源泄漏或逻辑断裂
- 最简单的规避方式是确保 future 生命周期覆盖任务完成,例如把 future 存在栈上、并在作用域末尾显式
get() - 若确实不需要结果,可用
std::async(std::launch::async, ...).wait();忽略返回值,但注意这会阻塞当前线程
{
auto f = std::async([]{ /* long task */ });
// 忘记 wait/get → 析构时 terminate!
} // f 被销毁,但任务可能还在跑
future 的核心约束其实就两条:状态只能读取一次,销毁前必须消费掉。其余所有问题,基本都是在这两条边界上踩出来的。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










