std::promise通过set_value()或set_exception()将结果传递给绑定的std::future,二者通过get_future()建立唯一关联,且promise只能设置一次结果,future只能get()一次。

std::promise 怎么把结果塞给 std::future
你写了个异步任务,想在主线程里拿到它的返回值,std::promise 就是那个“递结果的人”,std::future 是“等结果的人”。它们必须配对用,靠 get_future() 建立绑定关系。
-
std::promise只能调用一次set_value()(或set_exception()),重复调用会抛std::future_error,错误信息是std::future_errc::promise_already_satisfied - 如果 promise 对象被销毁前没调用
set_value(),对应 future 调用get()时会抛std::future_error,错误信息是std::future_errc::no_state - 别在线程里直接传
std::promise对象——它不可拷贝,只能移动;常见写法是在线程函数参数里接收std::promise,然后用&& std::move(p)调用set_value()
std::promisep; std::future f = p.get_future(); std::thread t([&p]{ p.set_value(42); // ✅ 正确 }); t.join(); int x = f.get(); // 阻塞直到 set_value 被调用
std::future::get() 为什么一调就卡住
get() 是阻塞式取值,而且只能调用一次。它内部会等待 promise 设置值(或异常),同时把 future 状态置为“已消费”——第二次调 get() 直接抛 std::future_error,错误信息是 std::future_errc::future_already_retrieved。
- 如果异步任务没结束、也没调
set_value(),get()就一直等,没有超时机制(除非用wait_for()或wait_until()先判断) - 想避免卡死,先用
f.wait_for(std::chrono::seconds(1)) == std::future_status::ready判断是否就绪 - 如果异步任务里抛了异常,要改用
p.set_exception(std::current_exception()),否则get()会 rethrow 那个异常
async 和 packaged_task 哪个更适合替代手写 promise/future
手动配 std::promise + std::thread 容易出状态管理问题;std::async 和 std::packaged_task 是更安全的封装。
-
std::async自动创建 promise/future 对,还管线程生命周期;但注意默认启动策略是std::launch::deferred(延迟执行),不加std::launch::async可能不真正并发 -
std::packaged_task把可调用对象包装成“能生成 future 的任务”,适合需要多次触发同一逻辑、或任务要进队列/延后执行的场景 - 三者返回的 future 都不能拷贝,只能移动;但
std::async返回的 future 在析构时若未调get(),会阻塞等待(这是很多人踩坑的地方)
auto f1 = std::async(std::launch::async, []{ return 42; });
int x = f1.get(); // ✅
std::packaged_task pt([]{ return 42; });
auto f2 = pt.get_future();
pt(); // 触发执行
int y = f2.get(); // ✅
多线程下 shared_future 怎么解决多次 get 的需求
普通 std::future 的 get() 只能调一次,但有时多个线程都想读结果,就得用 std::shared_future。
立即学习“C++免费学习笔记(深入)”;
- 它支持拷贝,每次拷贝都共享底层状态;所有副本调
get()都能得到相同结果(或异常) - 从普通 future 转成 shared_future 只能通过
share()成员函数,且原 future 会失效(变成空状态) - 性能上,
shared_future::get()内部有原子操作和锁,比普通 future 略重,但多数场景可忽略
std::promisep; auto sf = p.get_future().share(); // 原 future 失效 std::thread t1([&sf]{ int x = sf.get(); }); std::thread t2([&sf]{ int y = sf.get(); }); // ✅ 两个线程都能 get
最常被忽略的是 promise 生命周期和 future 消费时机的配合:promise 必须活到 set_value 完成,future 必须在 get 前没被 move 走或析构,且不能重复 get。这些约束不是语法报错,而是运行时报异常,调试起来容易绕弯。










