默认构造函数,如果程序员没有为类定义构造函数,那么编译器会在【需要的时候】为类合成一个构造函数,而【需要的时候】分为程序员需要的时候和编译器需要的时候,程序员需要的时候应该由程序员来做工作,编译器需要的时候则由编译器来做工作。
C++中,全局变量 / 对象的内存会被清零(如果类对象没有程序员定义的构造函数的时候),
而堆heap 或 栈stack上的变量或对象则不会被清零,其内存只取决于上一次这段内存的值。
而编译器什么情况下会为类合成默认构造函数呢?
会在以下四种情况合成默认的构造函数:
1、类中有一个或多个类对成员,而类对象成员又有一个默认的构造函数(不管这个默认构造函数是显式声明的还是由编译器合成的)
2、当类继承子一个基类,而这个基类有一个默认构造函数(不管这个默认构造函数是显式声明的还是由编译器合成的)
3、当类声明了一个或多个虚函数时
4、当类派生自一个继承链,其中有一个或多个虚基类时
先来讨论第一种情况:类中有一个或多个类对成员,而类对象成员又有一个默认的构造函数
如果类中这种情况,则编译器会为类合成一个默认的构造函数,其构造函数内部做到工作只是调用该对象成员的默认构造函数,这个时候就是编译器【需要的时候】,当有多个对象成员时,编译器调用他们构造函数的顺序是按照他们在类中声明的顺序。
对于该类的其他简单成员,编译器不会对其进行初始化,这部分工作则需要又程序员来完成。
二、当类继承子一个基类,而这个基类有一个默认构造函数
如果程序员没有为该类声明构造函数(而非默认构造函数),那么编译器会为该类合成一个默认构造函数。
特别的,当该了声明了若干个构造函数,而没有默认构造函数时,编译器则不会为该了合成默认构造函数,此时,编译器会去扩展现有的构造函数,在内部先去调用父类的默认构造函数,如果同时有类对象成员,那么去调用该类对象的默认构造函数,最后调用程序员的手动初始化代码。
三、当类声明了一个或多个虚函数时
四、当类派生自一个继承链,其中有一个或多个虚基类时
这两种情况都涉及到虚函数表指针vtpr的问题,所以都需要生成默认的构造函数来设置vtpr的合法值。
扩张行为:一个虚函数表(存放虚函数的地址),
一个虚函数表指针(指向虚函数表)
PS:两个误解:1任何类如果没有定义默认构造函数则编译器会合成一个出来
2编译器合成出来的默认构造函数会显式设定类中每个数据成员的默认值。
这两个都是错误的!
【C++对象模型】构造函数语意学之一 默认构造函数