C++内置与用户定义无参默认构造函数的差异问题
问题解答
可正常编译的代码
#include<iostream> using namespace std; class student{ int rollNumber; int age; public : student(){ } }; int main(){ student const s; }
无法通过编译的代码
#include<iostream> using namespace std; class student{ int rollNumber; int age; }; int main(){ student const s; }
核心规则说明
两种编译结果的差异和构造函数的实际运行逻辑无关,本质是C++标准对const类对象初始化有明确的强制约束:
当定义const限定的类类型对象时,如果调用编译器隐式生成的平凡默认构造函数对其做默认初始化,该代码是非法的。因为这种场景下创建出的const对象所有成员值都是不确定的垃圾值,且后续无法通过赋值修改,对象从创建开始就没有合法可用的确定状态,属于无意义的代码,标准直接要求编译器报错。
两种默认构造函数的差异
你提到的两种默认构造函数,在当前student类的场景下运行时执行逻辑完全一致:都不会对两个int类型的成员变量做任何初始化操作,成员值均为不确定的垃圾值。二者的本质区别是语言层面的属性标记不同:
- 用户手动编写的空无参构造函数,属于用户提供的构造函数,会让类的默认构造函数被标记为非平凡构造函数。编译器会默认你明确知晓该构造函数的行为,即便构造函数是空实现,也认为你有自己的设计意图(比如后续会补充逻辑、或者通过友元等方式操作成员等),因此不会触发上述const对象的初始化校验,允许编译通过。
- 未手动声明任何构造函数时,编译器自动生成的默认构造函数属于平凡默认构造函数(当类没有虚函数、虚基类,所有成员/基类都支持平凡构造时就会生成这类构造函数),编译器可以明确分析出该构造函数不会对任何成员做初始化操作,此时创建const默认初始化对象就会触发标准的禁止规则,直接编译报错。
额外验证
如果给第二段无法编译的代码中的对象做值初始化,修改为student const s{};,即使不手动编写默认构造函数,代码也可以正常编译。因为值初始化会将类中的内置int成员全部零初始化,const对象创建后就有确定的零值,符合const对象的合法性要求。
内容的提问来源于stack exchange,提问作者Kamaal
相关产品推荐
相关产品推荐

