C++编译错误:无法转换std::list (*)()为std::list*的原因及解决
问题原因与解决方案
这绝对是C++里最经典的语法陷阱之一——最令人头疼的解析(Most Vexing Parse),我来给你拆解得明明白白:
为什么会报错?
你写的这句代码:
std::list<Test1> l1();
编译器并没有把它当成「创建一个std::list<Test1>类型的默认构造对象l1」,而是把它解析成了一个函数声明:这个函数名叫l1,没有参数,返回值是std::list<Test1>类型。
C++的语法规则里有个优先级:当编译器遇到「类型名 标识符(参数列表)」的写法时,会优先判定为函数声明,哪怕参数列表是空的。
那接下来的std::list<Test1> *pl1 = &l1;自然就会报错了——你试图把一个**函数指针(指向无参、返回std::list<Test1>的函数)**赋值给普通的std::list<Test1>*对象指针,类型完全不匹配,编译器当然会抛出类型转换错误。
怎么规避这个问题?
有几种简单可靠的方式:
方法一:去掉空括号
直接写成:std::list<Test1> l1;这时候编译器会明确识别为创建一个默认构造的
std::list<Test1>对象,不会和函数声明混淆,这也是你已经发现的有效方式。方法二:使用花括号初始化(C++11及以后)
写成:std::list<Test1> l1{};这种初始化方式是C11引入的统一初始化语法,完全不会被编译器解析成函数声明,在复杂场景下(比如构造函数参数容易引发歧义时)更安全,也是现代C推荐的写法。
方法三:额外添加括号(不推荐,但兼容旧标准)
如果你需要兼容C++11之前的标准,也可以写成:std::list<Test1> l1((()));不过这种写法可读性差,不如前两种直观,所以一般不推荐使用。
内容的提问来源于stack exchange,提问作者Zain
相关产品推荐
相关产品推荐

