关于c++类初始化的一些问题

354 阅读3分钟

一、类静态、const成员变量初始化问题

1.对于类内的const引用成员变量,必须在初始化列表里对其赋值。且初始化之后不能为其再赋值(read-only)
2.对于static变量,必须在类内声明,在类外(main函数之前)定义,即分配内存。
3.对于static const 变量,能且只能在类内声明它时直接用等号赋值
4.对于没有默认无参构造函数的类成员变量,必须显式在初始化列表中对其初始化。
5.对于没有默认无参构造函数的父类(继承时),必须显式在初始化列表中对父类初始化。

需要注意的是,即使是private的static变量,一样可以在类外定义(初始化)。
如果使用了只有声明没有初始化的static变量,则报错:

image.png

二.类初始化顺序及效率问题

类对象的构造顺序显示,进入构造函数体后,进行的是计算,是对成员变量的赋值操作,显然,赋值和初始化是不同的,这样就体现出了效率差异,如果不用成员初始化类表,那么类对自己的类成员分别进行的是一次隐式的默认构造函数的调用,和一次赋值操作符的调用,如果是类对象,这样做效率就得不到保障。

构造函数调用顺序:
按照派生类继承基类的顺序,即派生列表中声明的顺序,依次调用基类的构造函数;

按照派生类中成员变量的声名顺序,依次调用派生类中成员变量所属类的构造函数;

执行派生类自身的构造函数。

三.类外全局、静态、非静态变量初始化问题

先前有文章说,局部非静态变量是一个随机值。但经过测试,类外无论是全局还是局部,无论静态还是非静态,编译器都已将其初始化为零。(可能是新版本做了优化)。

四.bss段与data段内存分配

全局变量

    全局变量无疑要在main函数开始前执行完成,但可细分为在编译时和在运行时初始化,即static initialization和dynamic initialization。

  • static initialization

静态初始化按照我的理解,是针对那些较为简单的,c++内部定义的数据结构,如int,double,bool及其数组结构的初始化。又可分为zero和const两种方式。

           对于zero初始化,编译时编译器将其分配在.bss段,不占用rom空间;而const初始化,也就是我们指定了全局变量的初始值,编译器会将其分配在.data段,占用romon空间。

  • dynamic initialization

这种初始化针对的是需要调用构造函数才能完成的初始化。这种初始化会在main函数执行前由运行时库调用对应的代码进行初始化。

    静态初始化先于动态初始化,这一点很好理解。静态初始化在编译时初始化,直接写进.bss和.data段,程序执行时直接加载,而动态初始化只能在运行时由运行时库调用相应构造函数

image.png