std::promise 与 std::future 机制中,set_value 是相对于 set_exception 的另一面。
如果说 set_exception 是用来报告“任务失败/出错了”,那么 set_value 就是用来提交“任务成功/结果算好了”。
它是 std::promise 类的一个成员函数,作用是将计算结果存入共享状态,并通知对应的 future:“数据准备好了,可以来取了。”
1. set_value 的三种形态
根据 std::promise<T> 模板参数 T 的不同,set_value 的用法略有区别:
A. 传递具体数据 (std::promise<int>, std::promise<string> 等)
这是最直观的用法。子线程算出了结果,通过 set_value 传回去。
// 场景:子线程计算 10 + 20
void worker(std::promise<int> prom) {
int result = 10 + 20;
// 【关键动作】提交结果
prom.set_value(result);
}
// 主线程:fut.get() 将会得到 30
B. 仅发送完成信号 (std::promise<void>)
这是您在之前的代码片段中看到的用法。 如果 T 是 void,说明我们不关心返回值,只关心“任务做完了没有”。
void worker(std::promise<void> prom) {
// 做一些耗时操作...
doHeavyWork();
// 【关键动作】不传参数,仅表示“我做完了”
prom.set_value();
}
// 主线程:fut.get() 只是解除阻塞,不返回任何数据
C. 传递引用 (std::promise<T&>)
较少见,用于直接传递对象的引用。
2. 完整工作流对比
我们可以把 std::promise 看作一个快递员。
-
set_value: 快递员把货物(正常结果)放进了快递柜。 -
set_exception: 快递员把损坏说明书(异常对象)放进了快递柜。 -
future.get(): 收件人(主线程)打开快递柜。如果里面是货,就拿走;如果里面是说明书,当场崩溃(抛出异常)。
3. 代码示例:成功与失败的双岔路
这个例子展示了 set_value 和 set_exception 如何在一个逻辑分支中配合工作:
void dataLoader(std::promise<std::string> prom, bool success) {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时
if (success) {
// --- 情况 1:成功 ---
// 使用 set_value 提交结果
std::string data = "核心机密数据: 42";
prom.set_value(data);
} else {
// --- 情况 2:失败 ---
// 使用 set_exception 提交错误
try {
throw std::runtime_error("下载数据超时!");
} catch (...) {
prom.set_exception(std::current_exception());
}
}
}
int main() {
// 创建 promise 和 future
std::promise<std::string> prom;
std::future<std::string> fut = prom.get_future();
// 启动线程 (尝试改为 false 看看效果)
std::thread t(dataLoader, std::move(prom), true);
std::cout << "主线程:正在等待数据..." << std::endl;
try {
// get() 会阻塞,直到 set_value 或 set_exception 被调用
std::string result = fut.get();
std::cout << "主线程:收到数据 -> " << result << std::endl;
} catch (const std::exception& e) {
std::cout << "主线程:捕获异常 -> " << e.what() << std::endl;
}
t.join();
return 0;
}
4. ⚠️ 重要注意事项:只能给一次
std::promise 的承诺是非常严肃的:你只能 set_value 或者 set_exception 一次。
如果你尝试在一个 promise 上调用两次设置(比如先 set_value 了一次,又 set_value 了一次),程序会抛出 std::future_error,错误码为 promise_already_satisfied。
prom.set_value(10);
prom.set_value(20); // ❌ 崩溃!抛出 std::future_error
总结: set_value 是多线程通信中“报喜”的通道。配合之前的 set_exception(报忧),它们构成了 C++ std::future 机制完整的结果交付闭环