std::future 和 std::promise 是 C++ 实现 Promise 语义的核心设施,支持跨线程结果传递:promise 为写端(set_value/exception),future 为读端(get/wait),二者通过线程安全共享状态绑定,且均仅可移动不可拷贝。

std::future 和 std::promise 就是 C++ 的 Promise 基础设施
JavaScript 的 Promise 核心语义是:异步任务启动后立即返回一个“占位对象”,后续通过 .then() 注册回调,或用 await 等待结果。C++ 标准库没提供链式 .then(),但 std::promise + std::future 已覆盖最核心能力:分离任务发起与结果消费,支持跨线程传递值或异常。
关键点在于:std::promise 是“写端”,负责设置结果;std::future 是“读端”,负责获取结果(可阻塞、可轮询、可等待)。两者通过共享状态绑定,这个状态默认在线程间安全。
常见错误现象:std::future 被拷贝(编译报错),或 std::promise 未被 set_value/set_exception 就析构(导致 std::future_error: broken promise)。
-
std::promise只能移动,不能拷贝;std::future同样只可移动 —— 这是强制你明确所有权转移 - 若用
std::async启动任务,它内部自动构造std::promise并返回std::future,省去手动配对 - 不要在未调用
set_value或set_exception前让std::promise离开作用域
如何实现 .then() 链式调用(手动版)
C++20 没原生 .then(),但可以用 std::thread 或 std::async 手动模拟:把前一个 std::future 的结果作为参数,传给下一个异步任务。
立即学习“Java免费学习笔记(深入)”;
典型场景:HTTP 请求 → 解析 JSON → 更新 UI。注意:每个 .then() 实际是新启一个异步操作,不是在原线程续执行。
示例逻辑:
auto p1 = std::promise<int>{};
auto f1 = p1.get_future();
std::async(std::launch::async, [&]{
std::this_thread::sleep_for(100ms);
p1.set_value(42);
});
// then
auto p2 = std::promise<std::string>{};
auto f2 = p2.get_future();
std::async(std::launch::async, [f1 = std::move(f1), &p2]{
auto val = f1.get(); // 阻塞直到 f1 就绪
p2.set_value("got: " + std::to_string(val));
});
性能影响:每次 .then() 都涉及一次线程调度和共享状态切换;如果只是简单计算,用同步调用更轻量。
- 必须显式 move
std::future到 lambda 捕获列表,否则编译失败 - 若前一个 future 抛异常,
f1.get()会 rethrow,需 try/catch 并调用p2.set_exception(...) - 没有内置取消机制,无法像 JS 的
AbortSignal那样中断链
避免踩坑:shared_future 和 wait_for 的正确用法
一个 std::future 只能被 get() 一次,但多个线程可能都需要读结果 —— 这时得用 std::shared_future。
错误做法:把同一个 std::future 传给多个线程,第二个线程调用 get() 会抛 std::future_error: no state。
正确做法:
- 从原始
std::future调用.share()得到std::shared_future - 用
wait_for()替代无条件get(),防止无限阻塞;返回值是std::future_status枚举 -
wait_for(0s)可用于轮询(类似 JS 的Promise.race([p, timeout]))
兼容性注意:std::shared_future 在 C++11 就存在,但 wait_until/wait_for 的超时精度依赖系统时钟,Windows 上可能只有 ~15ms 分辨率。
要不要自己封装 Promise 类?
如果你项目里大量需要 .then()、.catch()、Promise.all(),且团队熟悉 JS 语义,可以封装一层 —— 但别试图 1:1 复刻。
容易被忽略的复杂点:
- JS Promise 的 microtask 队列保证回调按注册顺序、在当前宏任务结束后立即执行;C++ 没等价机制,你得选线程池或事件循环来模拟
-
Promise.all()要求所有 future 就绪才 resolve,但任一失败就得 reject —— 需要同时监听多个std::future,而标准库不提供 wait-for-any-with-exception-awareness - 内存生命周期管理:回调 lambda 捕获的对象,可能比 promise 本身活得久,容易 dangling reference
多数情况下,直接用 std::promise/std::future + std::async 更清晰;真要高级抽象,优先考虑成熟库如 libunifex 或 cppcoro 的 task/future 实现。


















