关于派生类默认构造函数中基类内置类型成员初始化的疑问
关于派生类构造函数中
Derived() :Base1()写法的初始化行为解释 核心区别:值初始化 vs 默认初始化
要理解两种场景的不同结果,首先得明确C++中两种初始化规则的差异:
- 默认初始化:当对象创建时未指定任何初始化器(比如
Base1 b1;),内置类型成员不会被初始化,值为内存中的随机垃圾值;类类型成员则调用其默认构造函数。 - 值初始化:通过
Type()或Type{}的形式触发,对于没有用户定义构造函数的聚合类(比如你的Base1),会将所有内置类型成员自动初始化为0;有用户定义构造函数的类则调用其默认构造函数。
场景1:显式定义Derived() :Base1()的情况
你的代码中,派生类构造函数显式调用了Base1(),这会对基类子对象触发值初始化:
class Derived : public Base1{ public: int c; int d; Derived() :Base1(){ // 显式触发基类子对象的值初始化 } };
由于Base1是聚合类(无用户定义构造函数),值初始化会把它的内置类型成员a1、b1都设为0,所以通过rb1.a1访问的是已初始化的基类子对象成员,输出为0。
而直接声明Base1 b1;是默认初始化,a1保留垃圾值,所以输出-858993460。
场景2:使用using Base1::Base1;继承基类构造函数的情况
当你用using声明继承基类构造函数时,派生类的默认构造函数本质是继承了基类的编译器生成默认构造函数:
class Derived : public Base1{ public: using Base1::Base1; // 继承基类构造函数 int c; int d; };
这个继承来的构造函数对基类子对象执行的是默认初始化,不会初始化a1、b1,所以派生类对象中的基类成员同样是垃圾值,rb1.a1的输出和b1.a1一致。
Derived() :Base1()写法的特殊之处
这种写法的核心特殊点在于:
- 它绕过了编译器默认的基类子对象初始化逻辑,显式指定用值初始化方式初始化基类子对象。
- 即使基类没有显式定义构造函数,
Base1()这种表达式也会触发值初始化规则,强制将聚合类的内置类型成员设为0。 - 与之相对,编译器自动生成的派生类默认构造函数(或继承自基类的构造函数)只会对基类子对象执行默认初始化,不会处理内置类型成员的初始化。
内容的提问来源于stack exchange,提问作者Yiqun Cui
相关产品推荐
相关产品推荐

