在 C++11 中,std::future 是标准库中的一个强大工具,用于实现异步任务获取返回值。它与 std::async、std::promise 搭配使用,能够从并发任务中安全获取结果,是线程通信和异步执行的核心组件之一。
一、std::future 是什么?
- 它表示一个异步操作的结果,用于获取尚未完成任务的值。
- 通常与
std::async或std::promise搭配使用。 std::future<T>:未来某个时间点将拥有一个类型为T的结果。
二、典型使用场景
场景一:std::async + std::future(最常见,简单)
异步执行一个函数,主线程稍后使用 future.get() 获取其结果。
场景二:std::promise + std::future(手动控制结果传递)
适用于线程中产生结果、异常或信号时主动传递给主线程。
三、基础示例(使用 std::async)
#include <iostream>
#include <future>
#include <chrono>
// 一个耗时函数
int slow_add(int a, int b) {
std::this_thread::sleep_for(std::chrono::seconds(2));
return a + b;
}
int main() {
std::cout << "Starting async task...\n";
// 启动异步任务,立即返回 std::future 对象
std::future<int> result = std::async(std::launch::async, slow_add, 3, 4);
std::cout << "Doing other work...\n";
// 等待结果并获取(阻塞)
int value = result.get();
std::cout << "Result: " << value << std::endl;
return 0;
}
输出:
Starting async task...
Doing other work...
Result: 7
四、控制异步启动策略
std::future<int> f1 = std::async(std::launch::async, func); // 异步立即启动线程
std::future<int> f2 = std::async(std::launch::deferred, func); // 延迟执行(在 get() 时运行)
std::future<int> f3 = std::async(std::launch::async | std::launch::deferred, func); // 默认行为
五、std::promise 搭配 std::future
#include <iostream>
#include <future>
#include <thread>
void calculate(std::promise<int> p) {
std::this_thread::sleep_for(std::chrono::seconds(2));
p.set_value(42); // 设置结果
}
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future(); // 获取 future
std::thread t(calculate, std::move(prom)); // 线程中设置值
std::cout << "Waiting for result..." << std::endl;
int result = fut.get(); // 阻塞等待结果
std::cout << "Result: " << result << std::endl;
t.join();
return 0;
}
六、常用函数说明
| 函数名 | 功能说明 |
|---|---|
future.get() | 获取结果,阻塞直到就绪(只能调用一次) |
future.wait() | 阻塞直到任务完成 |
future.wait_for(dur) | 超时等待 |
future.wait_until(tp) | 等待到指定时间点 |
future.valid() | 判断是否持有共享状态 |
七、注意事项
std::future::get()只能调用一次,之后对象就失效(invalid)。- 若
async的函数抛出异常,该异常会被捕获,并在get()时重新抛出。 std::future不是线程安全的:多个线程不能同时访问同一个future。
八、进阶示例:多个任务并发执行并获取结果
#include <iostream>
#include <vector>
#include <future>
int work(int id) {
std::this_thread::sleep_for(std::chrono::milliseconds(100 * id));
return id * id;
}
int main() {
std::vector<std::future<int>> results;
for (int i = 1; i <= 5; ++i) {
results.push_back(std::async(std::launch::async, work, i));
}
for (auto& fut : results) {
std::cout << "Result: " << fut.get() << std::endl;
}
return 0;
}
九、数据预处理并行化综合示例
应用场景示例:点云数据批量预处理(并发执行)
假设有大量点云块(或图像帧)需要执行滤波、去噪、下采样等操作,顺序执行较慢。可以使用 std::async 启动多个线程并行处理每个数据块。
示例代码:点云块并行处理
#include <iostream>
#include <vector>
#include <future>
#include <random>
#include <chrono>
// 假设每个点云块是一个 vector<float>
using PointCloudBlock = std::vector<float>;
// 模拟预处理函数(如滤波、下采样等)
PointCloudBlock preprocessBlock(const PointCloudBlock& input, int blockId) {
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟耗时
PointCloudBlock result = input;
for (auto& p : result) {
p *= 0.9f; // 模拟处理
}
std::cout << "Block " << blockId << " processed\n";
return result;
}
int main() {
const int blockCount = 8;
// 模拟 8 个点云块
std::vector<PointCloudBlock> inputBlocks(blockCount, PointCloudBlock(1000, 1.0f));
std::vector<std::future<PointCloudBlock>> futures;
// 并发预处理每个块
for (int i = 0; i < blockCount; ++i) {
futures.push_back(std::async(std::launch::async, preprocessBlock, inputBlocks[i], i));
}
// 收集结果
std::vector<PointCloudBlock> processedBlocks;
for (auto& fut : futures) {
processedBlocks.push_back(fut.get());
}
std::cout << "All blocks processed.\n";
return 0;
}
多线程处理的好处
| 优点 | 说明 |
|---|---|
| 提高吞吐 | 并发预处理多个任务,CPU 多核资源充分利用 |
| 无需额外线程池 | 使用 std::async 自动调度线程 |
| 支持异常处理 | 若某个任务异常,future.get() 时可捕获 |
| 易于封装 | 可以包装为模块,适用于图像/点云/文本等任意数据 |
十、小结:何时用 future
- 想让线程返回值给主线程。
- 想延迟执行某个任务。
- 需要对异步任务的结果、超时、异常处理。
- 实现任务通信(如 promise 设置结果、主线程读取)。
8449

被折叠的 条评论
为什么被折叠?



