1."坑"的问题是什么?
先看一段代码:
class Functor
{
public:
void operator()()
{
std::cout << "我是线程的初始函数" << std::endl;
}
};
int main()
{
std::thread t(Functor());// 强制高速编译器这是一个构造函数!
t.join();
return 0;
}
按照正常的思路分析这段代码应该是这样的:
Functor类当中有一个"operator()"成员函数,这就注定Functor类对象是一个可调用对象(当成函数一样使用)。那么在"std::thread t(Functor())"当中,t的构造函数的参数是一个Functor类的匿名对象,也就相当于传递了一个线程的初始函数。这句代码之后,输出结果应该为"我是线程的初始函数"才对。
但是这段代码的结果却是:
啥玩意???竟然报错!!??后面反复编译了几次,依然是这个结果。这就让我陷入了沉思......
实际上"std::thread t(Functor())"被编译器解释成了一个函数声明。即,一个函数名为t,返回类型为std::thread,参数为函数指针(指向一个无参的,返回类型为Functor的函数)。
2.从另一个角度去看"坑"
先看这么一段代码:
int main()
{
std::vector<int> vec(std::string());
return 0;
}
放心,不报错,并且编译过。
它也被解释成了函数声明。问题就在于,它为什么被解释成一个函数声明?
如果我把它写成这样:
int main()
{
//std::vector<int> vec(std::string());
std::vector<int> func(std::string p());
return 0;
}
是不是就清楚多了?如果还不清楚,我再这样写一段代码:
int main()
{
//std::vector<int> vec(std::string());
std::vector<int> func(std::string p());
return 0;
}
std::string p()
{
return "";
}
清楚了吧!func后面的括号写的是一个函数。也就说,"std::vector<int> func(std::string p());"是一个函数声明,返回值为std::vector<int>,参数类型为一个函数指针(指向一个返回类型为std::string、无参的函数)。
再回看"std::vector<int> vec(std::string());"这句话,需要注意一个细节,那就是函数声明的形参类型可以不用给名字。这就透了吧!
还有一个问题,"std::vector<int> vec(std::string());"当中的"(std::string())"明明是一个函数,我为什么要说它是一个函数指针?这里又涉及到一个细节,在C/C++中,没有函数类型,这里的"(std::string())"会自动被解析成指针!
如果还不理解,看这么一段代码:
void test(int arr[]);
test函数接收的形参真的是一个数组吗?当然不是咯,这里的arr是一个指针!
3.解决方法
所以在C++11当中又补充了一个"初始化列表",像下面这么用:
class Functor
{
public:
void operator()()
{
std::cout << "我是线程的初始函数" << std::endl;
}
};
int main()
{
std::thread t{Functor()};// 强制告诉编译器这是一个构造函数!
t.join();
return 0;
}
所以最终的输出结果就是正确的咯!