面试题:请介绍 C++ 中 future、promise、packaged_task、async 的区别?

在 C++ 中,std::futurestd::promisestd::packaged_task 和 std::async 是用于异步编程的工具,它们共同构成了 C++11 引入的并发编程模型。以下是它们的区别和用途:


1. std::future

  • 作用
    • std::future 用于获取异步操作的结果。
    • 它表示一个可能尚未完成的异步计算的结果。
  • 常用操作
    • get():获取结果,如果结果未就绪,则阻塞当前线程。
    • wait():等待结果就绪。
    • valid():检查 future 是否关联了一个共享状态。

2. std::promise

  • 作用
    • std::promise 用于存储一个值或异常,并通过 std::future 获取。
    • 它允许手动设置异步操作的结果。
  • 常用操作
    • set_value():设置结果值。
    • set_exception():设置异常。
    • get_future():获取与 promise 关联的 future

3. std::packaged_task

  • 作用
    • std::packaged_task 是一个可调用对象的包装器,它将任务的返回值或异常与 std::future 关联。
    • 它适合将任务(如函数、lambda 表达式)与 future 绑定。
  • 常用操作
    • operator():执行任务。
    • get_future():获取与任务关联的 future

4. std::async

  • 作用
    • std::async 是一个高级封装,用于异步执行任务并返回 std::future
    • 它简化了异步任务的启动和结果获取。
  • 启动策略
    • std::launch::async:在新线程中异步执行任务。
    • std::launch::deferred:延迟执行任务,直到调用 future.get() 或 future.wait()

5. 对比与选择

工具作用适用场景
std::future获取异步操作的结果。需要获取异步任务的结果。
std::promise手动设置异步操作的结果(值或异常)。需要手动控制异步操作的结果。
std::packaged_task将任务与 future 绑定,适合包装可调用对象。需要将任务与 future 绑定。
std::async高级封装,简化异步任务的启动和结果获取。需要快速启动异步任务并获取结果。

6. 示例:综合使用

以下是一个综合示例,展示了 std::futurestd::promisestd::packaged_task 和 std::async 的使用:

#include <iostream>
#include <future>
#include <thread>
#include <stdexcept>

// 使用 std::async
void exampleAsync() {
    std::future<int> future = std::async(std::launch::async, [] {
        return 42;
    });
    std::cout << "Async result: " << future.get() << std::endl;
}

// 使用 std::promise
void examplePromise() {
    std::promise<int> promise;
    std::future<int> future = promise.get_future();

    std::thread t([](std::promise<int> p) {
        p.set_value(42); // 设置结果
    }, std::move(promise));

    std::cout << "Promise result: " << future.get() << std::endl;
    t.join();
}

// 使用 std::packaged_task
void examplePackagedTask() {
    std::packaged_task<int()> task([] {
        return 42;
    });
    std::future<int> future = task.get_future();

    std::thread t(std::move(task)); // 在新线程中执行任务
    std::cout << "Packaged_task result: " << future.get() << std::endl;
    t.join();
}

int main() {
    exampleAsync();
    examplePromise();
    examplePackagedTask();
    return 0;
}

7. 总结

  • std::future:用于获取异步操作的结果。
  • std::promise:用于手动设置异步操作的结果。
  • std::packaged_task:用于将任务与 future 绑定。
  • std::async:用于简化异步任务的启动和结果获取。

根据具体需求选择合适的工具,可以在 C++ 中实现灵活且高效的异步编程。

2 / 2

THE END
点赞6 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容