C++ 按值将std::thread推入列表

C++ 按值将std::thread推入列表,c++,multithreading,stdthread,C++,Multithreading,Stdthread,我的代码如下所示: #include <list> #include <thread> void my_function(int val) { // Empty function } int main() { std::list<std::thread> threads; for (int i = 0 ; i < 10 ; i++) { threads.push_back(std::thread(my_func

我的代码如下所示:

#include <list>
#include <thread>

void my_function(int val) {
    // Empty function
}

int main() {
    std::list<std::thread> threads;
    for (int i = 0 ; i < 10 ; i++) {
        threads.push_back(std::thread(my_function, i));
    }

    return 0;
}
#包括
#包括
无效我的_函数(int val){
//空函数
}
int main(){
std::列出线程;
对于(int i=0;i<10;i++){
threads.push_back(std::thread(my_函数,i));
}
返回0;
}
我使用
threads.push_back()
这一事实意味着我运行复制构造函数
std::thread::thread(constthread&)

  • 安全吗

  • 我应该使用
    std::move

请假设我事先不知道需要多少线程,所以用数组或
std::vector
替换列表对我来说不是一个选项(
std::vector
只有在我事先知道线程数的情况下才是一个选项,因为我负担不起向量的
realloc
操作)

我使用threads.push_back()这一事实意味着我运行复制构造函数

不,没有。因为C++11
push_back
被重载以接受对列表值类型的右值引用

无法运行
std::thread
的复制构造函数,因为它已声明为已删除。上面提到的
push_back
重载就是为了支持仅移动类型而添加的,比如线程句柄

如果您想在不移动的情况下直接将线程初始化到容器中,那么
emplace\u back
可以这样做。但是您需要在中传递
std::thread
构造函数的参数,而不是从中初始化的线程:

threads.emplace_back(my_function, i);
我使用threads.push_back()这一事实意味着我运行复制构造函数

不,没有。因为C++11
push_back
被重载以接受对列表值类型的右值引用

无法运行
std::thread
的复制构造函数,因为它已声明为已删除。上面提到的
push_back
重载就是为了支持仅移动类型而添加的,比如线程句柄

如果您想在不移动的情况下直接将线程初始化到容器中,那么
emplace\u back
可以这样做。但是您需要在中传递
std::thread
构造函数的参数,而不是从中初始化的线程:

threads.emplace_back(my_function, i);

“事实上,我使用
线程。push_back()
意味着我运行复制构造函数
std::thread::thread(const thread&)
”这样的构造函数是,所以您不可能运行它。为什么不使用
emplace_back
?听起来像是你在追求什么。“我应该使用std::move吗”不,临时值已经是右值,您需要使用
std::move
来强制转换命名变量。@somethingsthingsomething
std::thread(my_函数,I)
是右值
std::vector::push_back
对使用移动语义的右值有一个重载,并且不复制。@SomethingSomething-几乎。它是在调用站点构造的,因此引用可以绑定到它。然后,在列表节点内,通过在调用站点移动一个线程的内容来构造另一个线程。行动是安全的。只有一个句柄拥有线程。我必须支持Slava,你应该得到一本关于C++11的进修书来学习术语。“事实上,我使用
线程。push_back()
意味着我运行复制构造函数
std::thread::thread(const thread&)
”这样的构造函数是,所以你不可能运行它。为什么不使用
emplace_back
?听起来像是你在追求什么。“我应该使用std::move吗”不,临时值已经是右值,您需要使用
std::move
来强制转换命名变量。@somethingsthingsomething
std::thread(my_函数,I)
是右值
std::vector::push_back
对使用移动语义的右值有一个重载,并且不复制。@SomethingSomething-几乎。它是在调用站点构造的,因此引用可以绑定到它。然后,在列表节点内,通过在调用站点移动一个线程的内容来构造另一个线程。行动是安全的。只有一个句柄拥有线程。我必须支持Slava,你应该得到一本关于C++11的进修书来学习术语。这是否意味着代码是安全的?就像我将线程直接分配给列表中的占位符一样?@SomethingSomething-是的,就线程创建本身而言,它是安全的。标准库删除复制构造函数,这样不安全的创建甚至不会编译。而move构造函数做的是理智的事情。它的目的是通过构造正确。这是否意味着代码是安全的?就像我将线程直接分配给列表中的占位符一样?@SomethingSomething-是的,就线程创建本身而言,它是安全的。标准库删除复制构造函数,这样不安全的创建甚至不会编译。而move构造函数做的是理智的事情。它的目的是通过构造来纠正错误。