Most vexing parse(最烦人的解析)
引言
Most vexing parse 是 effective c++ 书中写到的,写本文是为了讲清这到底是什么.
错误的方式
#include <iostream>
class A {
public:
A(const std::string& name){
std::cout << name << std::endl;
}
};
int main()
{
char szTemp[] = "test";
A a(std::string(szTemp));
//A a(std::string())//同样没有输出
return 0;
}
上面写了一个简单的类,构造函数允许传入一个string类型的引用,然后输出。
在main
函数中我们的本意是创建一个A类型的对象
,并且传入szTemp的string
,让其在构造函数中输出
。
但是却发现什么也没有输出,这是什么原因呢?
Most vexing parse 解释
在C++中,如果出现 T1 t1Name(T2(t2Name))
,C++会将它解释成T1 t1Name(T2 t2Name)
函数声明。
拿上面弄得栗子讲:
A a(std::string(szTemp))
被解释成了 A a(std::string szTemp)
的函数声明。
如果我们将A a(std::string(szTemp))
替换成A a(std::string("test"))
,或者将A a(std::string())
替换成A a(std::string(""))
就不会有任何问题。
证明
通过打印 std::cout << typeid(a).name();
可以发现类型根本不是class a
,而是一个function.
下面的代码我们将A a(std::string(szTemp))
真正定义出来。
#include <iostream>
class A {
public:
A(const std::string& name){
std::cout << name << std::endl;
}
};
char szTemp[] = "test";
A a(std::string(szTemp)){
//这里的szTemp并不是全局变量的szTemp
//而是函数形参,还记得上面说过
//被解释成了 A a(string szTemp)
std::cout << szTemp + " 新的输出" << std::endl;
return A(szTemp);
}
int main()
{
//这里的a是function,会返回一个A类型的对象
//所以不存在T1 t1name,T2 t2name 同时出现的问题。这是一个赋值语句。
char test[]="haha";
A obj = a(std::string(test));
return 0;
}
输出结果:
test 新的输出
test
如何避免
使用C++的方式来传参。
- A a{ std::string(szTemp) };
- 先创建string字符串
std::string str(szTemp) ;
A a(str);
- 直接使用常量
A a(std::string(“test”) );
这样仅仅是T1 t1name(T2(常量))
只要避免T1 t1name T2 t2name 同时出现即可。