C++避坑——most vexing parse问题

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类的匿名对象,也就相当于传递了一个线程的初始函数。这句代码之后,输出结果应该为"我是线程的初始函数"才对。

但是这段代码的结果却是:

C++避坑——most vexing parse问题_第1张图片

啥玩意???竟然报错!!??后面反复编译了几次,依然是这个结果。这就让我陷入了沉思...... 

实际上"std::thread t(Functor())"被编译器解释成了一个函数声明。即,一个函数名为t,返回类型为std::thread,参数为函数指针(指向一个无参的,返回类型为Functor的函数)。

2.从另一个角度去看"坑"

先看这么一段代码:

int main()
{
	std::vector vec(std::string());
	return 0;
}

放心,不报错,并且编译过。

它也被解释成了函数声明。问题就在于,它为什么被解释成一个函数声明?

如果我把它写成这样:

int main()
{
	//std::vector vec(std::string());
	std::vector func(std::string p());
	return 0;
}

是不是就清楚多了?如果还不清楚,我再这样写一段代码:

int main()
{
	//std::vector vec(std::string());
	std::vector func(std::string p());
	return 0;
}
std::string p()
{
	return "";
}

清楚了吧!func后面的括号写的是一个函数。也就说,"std::vector func(std::string p());"是一个函数声明,返回值为std::vector,参数类型为一个函数指针(指向一个返回类型为std::string、无参的函数)。

再回看"std::vector vec(std::string());"这句话,需要注意一个细节,那就是函数声明的形参类型可以不用给名字。这就透了吧!

还有一个问题,"std::vector 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;
}

所以最终的输出结果就是正确的咯!

 

你可能感兴趣的:(c++,开发语言)