std::promise和std::future必须成对使用,future须由promise::get_future()获取,否则调用wait()/get()会抛no_state异常;promise只能set一次,future可拷贝共享状态但move后失效;std::async更安全,但默认启动策略含deferred,需显式指定async才确保异步;get()移动或复制结果且使future失效,多次调用UB;promise析构前未set将terminate。

std::promise 和 std::future 必须成对出现,单用没意义
你不能只声明一个 std::future 就指望它自动绑定到某个异步计算上——它必须从 std::promise 的 get_future() 拿到,否则调用 wait() 或 get() 会卡死或抛 std::future_error(错误码为 no_state)。
典型误用:std::future<int> f;</int> → 这是个空 future,没关联任何 promise,后续任何阻塞操作都非法。
- 正确流程:先构造
std::promise<t></t>,再调用它的get_future()获取对应std::future<t></t> - promise 和 future 可跨线程传递,但 promise 只能被 set 一次(
set_value()/set_exception()),重复调用会抛异常 - future 可以拷贝(浅拷贝),但每个 copy 都共享同一状态;move 后原对象变空(
valid() == false)
std::async 是更安全的替代方案,别硬手写 promise/future 组合
除非你要精确控制 promise 生命周期、或需要把结果分发给多个 future(比如一对多广播),否则直接用 std::async 更省心。它内部自动管理 promise/future,并默认在新线程执行(std::launch::async)。
常见误区:以为 std::async 总是异步——其实默认策略是 std::launch::async | std::launch::deferred,意味着可能延迟执行(等你调 get() 时才同步跑),导致“异步”假象。
- 强制异步:用
std::async(std::launch::async, []{ return 42; }) - 延迟执行(同步):用
std::async(std::launch::deferred, ...) - 不加策略参数时,编译器可自由选择;MSVC 默认倾向 deferred,GCC/Clang 多数情况 async,行为不一致
get() 会移动值,多次调用会触发未定义行为
std::future<t>::get()</t> 不仅阻塞等待,还会把存储的结果**移动出来**(对右值引用类型)或**复制出来**(对非移动友好类型)。调用完后,该 future 对象进入无效状态(valid() == false)。
立即学习“C++免费学习笔记(深入)”;
错误示例:
auto f = std::async([]{ return std::string("hello"); });<br>std::string s1 = f.get();<br>std::string s2 = f.get(); // UB!f 已 invalid
- 检查是否有效:调用前先判断
f.valid() - move-only 类型(如
std::unique_ptr)只能 get 一次,且接收变量必须是右值引用或用std::move接收(实际由返回值优化隐式处理) - 如果要多次读取结果,改用
std::shared_future(通过future.share()获得)
线程销毁早于 promise.set_xxx(),会导致程序终止
最隐蔽也最致命的问题:启动一个线程去计算并 set_value,但主线程提前退出、或线程函数结束而 promise 仍未 set,此时 promise 析构会调用 std::terminate()(C++11 起标准规定)。
原因:promise 析构时若内部状态仍为“未就绪”,且无人持有其 future,则直接 abort。
- 确保 promise 生命周期覆盖整个异步操作完成过程(比如把 promise 放在 lambda 捕获中,或作为类成员长期持有)
- 更稳妥做法:在线程函数末尾加 try/catch,并保证至少调用一次
set_value()或set_exception() - 避免裸线程 + promise 组合;优先用
std::async或封装好的 task 类(如基于std::packaged_task)



















