为什么我们可以直接将函数对象推送到 std::thread?

Why can we push function object to std::thread directly?

提问人:Peter 提问时间:9/10/2022 最后编辑:Peter 更新时间:9/10/2022 访问量:101

问:

我有点困惑为什么我们可以做这样的事情:

std::vector<std::thread> vec;
vec.reserve(2);
vec.emplace_back(std::bind(silly, 1));
vec.emplace_back(std::bind(silly, 2));

for (auto i = 0; i < vec.size(); i++) {
    vec[i].join();
}
// for folks who see this post after
// you can use push_back() like this:
vec.push_back(std::thread(std::bind(silly, 3)));

上面的代码,我们直接将函数对象推送到线程向量,我不知道为什么可以接受。因为据我所知,线程向量只能将线程类型对象推送到它。就像 int 向量一样,我们只能将 int 类型的对象推送到它。

下面的例子是我能 100% 理解的,因为我们将线程对象推入线程向量!

std::vector<std::thread> vecOfThreads;
std::function<void()> func = []() {
    //Do Some Important Work
    // .....
    //Print Thread ID
    std::cout << "From Thread ID : " << std::this_thread::get_id() << "\n";
};
vecOfThreads.push_back(std::thread(func));
std::thread th1(func);
vecOfThreads.push_back(std::move(th1));
for (std::thread &th: vecOfThreads) {
    // If thread Object is Joinable then Join that thread.
    if (th.joinable())
        th.join();
}

任何关于学习这部分的解释和建议的材料都是值得赞赏的!

C++ 多线程标准

评论

2赞 Some programmer dude 9/10/2022
你不推,你去。它通过将参数转发到构造函数来就地创建对象。这有点类似于放置新。emplace_backstd::thread
0赞 Peter 9/10/2022
@Someprogrammerdude,哎呀,我有点忘了。是的,因为它emplace_back!emplace_back() 将显式调用构造函数。所以实际上关于 vec.emplace_back(std::bind(silly, 1)) 发生的事情是调用 vec.emplace_back(std::thread(std::bind(silly, 1)));右?🙂
2赞 Alceste_ 9/10/2022
@Peter 不,emplace_back() 是一个专用函数,它接收构造函数的参数作为参数。所以它真的在召唤.但是,构造函数在内部使用,在 中。vec.emplace_back(std::bind(silly, 1))std::thread(std::function &)emplace_back
0赞 Peter 9/10/2022
看来我以前有错误的理解。感谢您的进一步解释@Alceste_ 🙂

答:

0赞 Alceste_ 9/10/2022 #1

编辑:我错过了代码示例,如评论中所述,在这种特殊的emplace_back情况下,构造函数是在不经过隐式转换链的情况下调用的,这是emplace_back的目的。尽管如此,剩下的还是留下了,因为问题是关于推动的。

C++ 提供隐式转换,这使您能够执行以下操作:

double a = 0;

不会因将 int 文本 (0) 分配给双精度类型变量 (a) 而出现错误。

上面的链接可以给你关于隐式转换的详细说明,但我们感兴趣的部分是:

用户定义的转换由零个或一个非显式单参数转换构造函数或非显式转换函数调用组成

文档中,有一个构造函数接受 std::函数(以及可选的参数),因此它可以用来在推送到线程向量时自动将函数转换为线程,如果链的其余部分得到尊重(显然不是)。在代码示例中,它直接调用,没有隐式转换限制。std::thread

评论

0赞 Peter 9/10/2022
感谢您的回复。我确实意识到这是emplace_back的魔力!我发现如果我用 push_back 替换 emplace_back,那么该行会显示错误!如果我想在这里使用 push_back(),我必须push_back(std::thread(std::bind(silly, 2)))