编译器误将变量声明识别为函数原型的原因与解决方法
解析C++的"最令人头疼的语法歧义"与解决方案
这个问题是C++里经典到让人挠头的Most Vexing Parse(最令人头疼的语法歧义),我来给你掰扯清楚前因后果:
为什么编译器会把它当成函数声明?
C++的语法解析规则有个优先级:当一条语句既可以被解释为变量定义,又可以被解释为函数声明时,编译器会优先选择函数声明的解析方式。
看你写的这行代码:
B b(A());
编译器会这么拆解:
B:函数的返回值类型b:函数的名字A():这不是你以为的A类临时对象,而是一个无参数、返回A类型的函数指针参数(在函数参数列表里,A()等价于A(*)())
所以整行被解析成:声明一个名为b的函数,它接收一个"无参且返回A类型"的函数指针作为参数,函数的返回值是B类型。这完全偏离了你用A临时对象构造B变量的意图,所以编译器抛出C4930警告来提醒你。
正确的实现方式
有几种靠谱的写法可以绕开这个歧义,根据你的C++版本选择就行:
1. 给临时对象加额外括号(兼容所有C++版本)
用括号把A()包裹起来,让编译器无法把它解析成函数参数声明:
B b( (A()) );
2. 使用列表初始化(C++11及以后)
C++11引入的列表初始化语法可以彻底避免这种歧义,写法更简洁:
B b{A()};
3. 显式创建临时变量(最直观)
先定义一个A类型的对象,再用它构造B,完全不会有歧义:
A temp; B b(temp);
4. 用auto推导构造(C++11及以后)
利用auto的类型推导特性,让编译器明确识别这是变量定义:
auto b = B(A());
内容的提问来源于stack exchange,提问作者Serge Rogatch
相关产品推荐
相关产品推荐

