我正在阅读有关c ++ 11多线程的文档,并且遇到了std::thread
的这个示例。
代码:
void thread_task(int n) {
...
}
int main(int argc, const char *argv[])
{
std::thread threads[5];
for (int i = 0; i < 5; i++) {
threads[i] = std::thread(thread_task, i + 1);
}
return 0;
}
我不明白threads[i] = std::thread(thread_task, i + 1);
。 std::thread
是一个静态函数调用,并返回std :: thread对象的引用吗?听起来不可思议,但似乎是代码所说的。
因为我会这样写:
std::thread *threads[5];
for (int i = 0; i < 5; i++) {
threads[i] = new std::thread(thread_task, i + 1);
}
感谢。
答案 0 :(得分:13)
让我们详细了解正在发生的事情:
std::thread threads[5];
这将创建一个由5个std::thread
个对象组成的数组,这些对象是默认构造的。目前它们代表“不是一个线程”,因为这是状态默认构造离开它们。
for (int i = 0; i < 5; i++) {
threads[i] = std::thread(thread_task, i + 1);
}
这使用operator=
的移动形式。由于线程不可复制,只能移动,thread& operator=(thread&& t)
定义thread& operator=(const thread& t)
。这会将threads[i]
中的线程对象分配给新构造的std::thread(thread_task, i + 1);
。
这里没有理由使用指针数组。它只会增加内存泄漏的可能性。
答案 1 :(得分:2)
std::thread
是否为静态函数调用,并返回std::thread
对象的引用?
不,它正在创建一个临时线程对象;就像int(42)
创建一个临时整数一样。赋值将其移动到数组中,因为线程是可移动的,并且临时值可以从中移动。
因为我会这样写:
您正在引入动态分配,额外的间接级别和内存泄漏(除非您在完成时添加代码以删除它们),这是没有充分理由的。
答案 2 :(得分:2)
std::thread
的{{3}}创建一个不代表线程的实例。作业是default constructor,因为也不允许复制。它将std::thread(thread_task, i + 1);
创建的实例移动到数组中。
答案 3 :(得分:2)
此:
std::thread(thread_task, i + 1)
是对std :: thread构造函数的调用,它创建一个新的线程对象并向它传递一个指向thread_task函数的指针,该函数本身是以i + 1作为参数调用的。
赋值是移动赋值(因为右侧是指匿名对象),而不是复制赋值。请注意,将删除std :: thread复制构造函数和复制赋值运算符。
这实际上比使用指针更简洁,因为当线程数组超出范围时,std :: thread对象将被自动销毁。