当前位置:首页 > 技术 > 正文内容

C++ 中 std::future 与异步任务的灵活应用

访客 技术 2026年7月9日 5

在现代 C++ 编程中,std::future 是处理异步操作结果的重要工具。它通常与 std::async 配合使用,能够以简洁的方式启动后台任务并安全地获取其返回值。以下通过多个代码实例展示如何结合 lambda 表达式、函数对象以及参数传递来实现高效的多线程异步计算。

使用 Lambda 执行延迟计算

lambda 表达式是定义轻量级可调用对象的理想选择。下面的例子演示了如何通过 std::async 在独立线程中运行一个延迟返回数值的 lambda:

#include <iostream>
#include <future>
#include <chrono>

int main() {
    auto task = std::async(std::launch::async, []() {
        std::this_thread::sleep_for(std::chrono::milliseconds(800));
        return 123;
    });

    std::cout << "等待结果...\n";
    int outcome = task.get();
    std::cout << "接收到结果: " << outcome << '\n';

    return 0;
}

封装逻辑于函数对象

对于更复杂的业务逻辑,可以将行为封装在类中,并重载调用运算符。这种方式提高了代码的可读性和复用性:

#include <iostream>
#include <future>

class DataProcessor {
public:
    int operator()() const {
        // 模拟耗时处理
        std::this_thread::sleep_for(std::chrono::seconds(1));
        return 999;
    }
};

int main() {
    DataProcessor worker;
    auto handle = std::async(std::launch::async, worker);

    std::cout << "正在处理数据...\n";
    int value = handle.get();
    std::cout << "处理完成,输出为: " << value << '\n';

    return 0;
}

Lambda 捕获局部变量进行异步运算

lambda 支持按值或引用捕获外部作用域中的变量。以下示例展示了如何将两个本地变量复制到异步上下文中执行乘法运算:

#include <iostream>
#include <future>

int main() {
    int base = 7;
    int multiplier = 6;

    auto computation = std::async(std::launch::async, [base, multiplier]() {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        return base * multiplier;
    });

    std::cout << "计算 " << base << " × " << multiplier << " 的结果\n";
    int result = computation.get();
    std::cout << "结果: " << result << '\n';

    return 0;
}

向函数对象传递参数

除了无参调用,std::async 还支持向可调用实体传入额外参数。此特性适用于需要动态输入的任务:

#include <iostream>
#include <future>

struct SquareCalculator {
    int operator()(int x) const {
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
        return x * x;
    }
};

int main() {
    int num = 13;
    auto future_result = std::async(std::launch::async, SquareCalculator{}, num);

    std::cout << "计算 " << num << " 的平方...\n";
    int answer = future_result.get();
    std::cout << "答案: " << answer << '\n';

    return 0;
}

带状态的异步任务(Lambda 参数捕获)

当需要在异步任务中使用变化的输入时,可通过值捕获确保数据在线程间安全共享:

#include <iostream>
#include <future>

int main() {
    double amount = 25.5;
    double rate = 1.1;

    auto tax_task = std::async(std::launch::async, [amount, rate]() {
        return amount * rate;
    });

    std::cout << "含税金额: " << tax_task.get() << '\n';

    return 0;
}

这些示例体现了 std::futurestd::async 在不同场景下的适应能力。无论是简单的闭包还是结构化的函数对象,都可以轻松集成进异步工作流中,提升程序并发性能的同时保持接口清晰。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。