究竟是如何执行std :: async的?

时间:2018-05-27 16:29:56

标签: c++ multithreading c++11 asynchronous

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

#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   构造函数   布展构造函数   布展构造函数   析构函数   FUNC()   析构函数   析构函数   3

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

  

0   构造函数   布展构造函数   布展构造函数   析构函数   析构函数   析构函数   3

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

1 个答案:

答案 0 :(得分:2)

  

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

因为呼叫是,延迟。它只会在您实际请求其结果后才会启动,例如通过致电get()了解未来(你没有做过):

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

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

这是一个实现定义,是否以及对复制构造函数的调用次数。建立它,例如在clang中,我甚至给了移动构造函数三个调用。因此,不要为此烦恼。但是如果你这样做,你必须自己研究标准库的实现。