首页 > 解决方案 > std::async 究竟是如何执行的?

问题描述

我想知道下面的代码是如何工作的?

#include <thread>
#include <future>
#include <set>
#include <iostream>
struct Task;
std::set<const Task*> dead_tasks;
struct Task
{
   ~Task() { dead_tasks.insert(this); std::cout << "dtor\n";}
   Task() { std::cout << "ctor\n";}
   Task(Task&&) { std::cout << "move-ctor\n";}
   void operator()() const { std::cout << "func()\n"; }
};
int main(){
   std::cout << dead_tasks.size() << '\n';
   std::async(std::launch::async, Task());
   std::cout << dead_tasks.size() << '\n';
}

此代码打印

0 ctor move-ctor move-ctor dtor func() dtor dtor 3

如果我们使用 std::launch::deferred 而不是 std::launch::async 我们将得到

0 ctor move-ctor move-ctor dtor dtor dtor 3

所以在后者中我们错过了成员函数调用。为什么?我可以理解对默认构造函数的调用和对移动构造函数的调用的存在。Task() 调用默认构造函数,然后 std::async 调用移动构造函数......但是我错过了第二次调用移动构造函数和调用成员函数背后的想法。我可以认为第二个移动构造函数是由 std::future 调用的,不是吗?

标签: c++multithreadingc++11asynchronous

解决方案


所以在后者中我们错过了成员函数调用。为什么?

因为电话被推迟了。它只会在您实际请求其结果时开始,例如通过调用get()未来(您没有):

auto fut = std::async(std::launch::deferred, Task());
fut.get();

我可以认为第二个移动构造函数是由 std::future 调用的,不是吗?

这是相当由实现定义的,是否会调用以及调用多少次复制构造函数。例如在 clang 中构建它甚至给了我三个对 move-constructor 的调用。因此,只是不要打扰它。但是如果你这样做了,你必须研究标准库实现本身,如果有的话。


推荐阅读