我想知道以下代码是如何工作的?
#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调用的,不是吗?
答案 0 :(得分:2)
所以在后者中我们错过了成员函数调用。为什么呢?
因为呼叫是,延迟。它只会在您实际请求其结果后才会启动,例如通过致电get()
了解未来(你没有做过):
auto fut = std::async(std::launch::deferred, Task());
fut.get();
我可以认为第二个移动构造函数是由std :: future调用的, 不能吗?
这是一个实现定义,是否以及对复制构造函数的调用次数。建立它,例如在clang中,我甚至给了移动构造函数三个调用。因此,不要为此烦恼。但是如果你这样做,你必须自己研究标准库的实现。