std::future 和 std::promise 是 C++11 提供的异步结果传递机制:promise 用于设置单次结果,future 用于获取该结果,二者共享状态、不可拷贝、需成对使用,且 future 必须调用 get() 或 wait() 否则异常时程序终止。

std::future 和 std::promise 是 C++11 引入的一对协作机制,用来在异步任务中安全地传递单次结果 —— 不是“怎么启动异步”,而是“怎么拿到那个还没算出来的值”。
std::promise 用来“塞结果”,std::future 用来“取结果”
它们必须成对出现:一个线程通过 std::promise::set_value()(或 set_exception())写入结果,另一个线程通过 std::future::get() 读取。一旦写入,就不能再写;一旦读取(get() 返回),该 std::future 就失效了。
常见错误现象:
- 对同一个
std::promise多次调用set_value()→ 程序直接 terminate - 没调用
set_value()就调用std::future::get()→ 阻塞到超时或永远卡住(除非用wait_for()) - 把
std::future移动走后,原对象再调用get()→ 抛出std::future_error(错误码为no_state)
如何从 std::async / std::thread / 手动线程中获取 future
最常用路径是 std::async,它自动构造 std::promise 并返回 std::future:
立即学习“C++免费学习笔记(深入)”;
auto fut = std::async(std::launch::async, []{ return 42; });
int x = fut.get(); // 阻塞等待,拿到 42
但若你手动管理线程(比如用 std::thread),就得自己配对 std::promise 和 std::future:
std::promiseprom; std::future fut = prom.get_future(); std::thread t([&prom]{ // 模拟耗时计算 std::this_thread::sleep_for(100ms); prom.set_value(123); // 注意:不能用 prom = ...,只能调 set_xxx }); t.detach(); // 或 t.join() // 主线程中 int y = fut.get(); // 成功拿到 123
关键点:
-
std::promise和std::future之间只共享状态,不共享数据内存 —— 所以能跨线程安全传递 - 必须用
std::move传递std::promise给线程函数,否则编译失败(std::promise不可拷贝) -
std::future默认也不可拷贝,但可移动;C++20 起支持std::shared_future实现多消费者
std::future::wait_for() 和 wait_until() 的实际用途
阻塞式 get() 容易导致线程“死等”,尤其在网络 I/O 或不确定耗时场景下。这时应优先用带超时的等待:
auto fut = std::async([]{ std::this_thread::sleep_for(2s); return "done"; });
if (fut.wait_for(1s) == std::future_status::ready) {
std::cout << fut.get() << "\n";
} else {
std::cout << "timeout\n";
}
注意:
-
wait_for()返回std::future_status::timeout并不表示任务失败,只是还没完成;后续仍可再调wait_for()或直接get() - 如果任务已抛异常,
get()会重新抛出该异常(不是std::future_error) -
wait_for()在 Windows 上可能有几十毫秒误差,别依赖它做精确定时
真正容易被忽略的是:std::future 的生命周期管理。一旦 std::future 对象析构而没人调过 get(),且对应 promise 已被设置值(尤其是异常),程序会直接 terminate —— 这不是 bug,是标准强制要求的“未消费异常必须爆炸”,所以务必确保每个 std::future 都被 get() 或 wait() 过。










