线程随着 std::thread 类型实例的创建而创建

从 C++ 11 开始,推荐使用列表初始化的方式,构造类类型的变量。

当函数的名字被当做一个值来使用的时候,实际上使用的是函数的指针

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <thread> // 1

void greeting() { // 2
std::cout << "Hello multithread!" << std::endl;
return;
}

int main() {
std::thread t{greeting}; // 3
t.join(); // 4
return 0;
}

std::thread wk_thread(ThreadTask()); // 1

std::thread wk_thread{ThreadTask{}}; // 2

在 (1) 处,作者的本意,是想构造一个 ThreadTask 实例,作为可调用对象作为 wk_thread 线程的线程函数。但实际上,ThreadTask() 是一个函数指针的类型——这个函数没有参数 (void),返回值的类型是 ThreadTask。因此,整个 (1) 会被 C++ 理解为一个函数声明:参数是一个函数指针(前述),返回类型是 std::thread

构造函数和普通的函数是有一些不同的。构造函数执行完毕之后,就产生了一个可用的实例。产生这样误解的本质原因,是 std::thread构造函数也是函数,因而采用 () 接受参数列表;这样一来,从形式上构造函数就没有任何特殊性了。C++ 11 引入了列表初始化的概念,允许程序员以花括号代替圆括号,将参数传递给构造函数。这样一来,(2) 就没有歧义了。