You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++无返回值函数异步任务执行与std::future<void>必要性探究

问题描述

第一个示例代码中所有任务均可成功启动且无异常,但第二个示例仅首个任务启动后程序便停滞,无法执行后续代码。我无法理解为何即使类A、B、C、D的仿函数无返回值(void),仍需定义std::future类型对象?

示例代码

Example #1

int main()
{
    A a("A");
    B b("B");
    C c("C");
    D d("D");
    Controller controller("Controller");

    // Resources shared between threads
    SharedResource sharedResource;
    ControllerResource controllerResource;

    std::future<void> taskA = std::async(std::launch::async, a, std::ref(sharedResource));
    std::future<void> taskB = std::async(std::launch::async, b, std::ref(sharedResource));
    std::future<void> taskC = std::async(std::launch::async, c, std::ref(sharedResource));
    std::future<void> taskD = std::async(std::launch::async, d, std::ref(sharedResource));
    std::thread thController(controller, std::ref(controllerResource), std::ref(sharedResource));
    thController.join();
}

Example #2

int main()
{
    A a("A");
    B b("B");
    C c("C");
    D d("D");
    Controller controller("Controller");

    // Resources shared between threads
    SharedResource sharedResource;
    ControllerResource controllerResource;

    std::async(std::launch::async, a, std::ref(sharedResource));
    std::async(std::launch::async, b, std::ref(sharedResource));
    std::async(std::launch::async, c, std::ref(sharedResource));
    std::async(std::launch::async, d, std::ref(sharedResource));

    std::thread thController(controller, std::ref(controllerResource), std::ref(sharedResource));
    thController.join();
}

问题解答

问题的核心在于**std::async返回的临时std::future对象的析构特性**:

  • 当你调用std::async但不保存返回值时,会生成一个临时的std::future对象。这个对象在当前语句执行结束后就会被销毁,而std::future的析构函数会强制阻塞当前线程,直到对应的异步任务完全执行完毕。
  • 第二个示例中,第一个std::async调用生成的临时std::future在析构时,会卡住主线程,必须等A的任务跑完才会执行下一行代码。如果A的任务是持续运行的(比如死循环、等待未触发的信号),主线程就会一直停滞在这里,永远无法启动后续的B、C、D任务和控制器线程。

而第一个示例中,你把每个std::async返回的std::future都存储到了变量中,这些变量直到main函数结束才会被销毁,因此所有异步任务可以和控制器线程并行执行,不会提前阻塞主线程。

不管仿函数的返回值是void还是其他类型,std::async都会返回对应类型的std::future(void返回值对应std::future<void>),上述的析构阻塞规则对所有情况都适用。

内容的提问来源于stack exchange,提问作者sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:06:40