概述
- 涉及初始化顺序的目标包括
- 静态成员变量
- 全局成员变量
- 类的成员变量
静态成员变量和全局成员变量
概述
- 静态成员变量
- 包括全局静态成员
- 也包括类的静态成员
顺序结论
- 全局变量 和 静态成员变量 在程序启动时初始化,具体顺序是以 编译单元 为单位
- 不同编译单元中的变量初始化顺序未定义
- 但同一个编译单元中的变量会按照它们 定义的顺序 初始化
1 2 3 4 5 |
class MyClass { public: static int x; }; int MyClass::x = 10; // 静态成员变量初始化 |
类的成员变量
概述
- 对于类对象,成员的初始化顺序严格按照 它们在类中声明的顺序 来执行,而不是按照构造函数中列出的顺序
顺序结论
成员初始化列表
中的变量会被用来初始化成员变量声明时直接初始化
的变量(C++11 引入的默认成员初始值)会在没有提供显式初始化时
生效- 构造函数内部的初始化代码是在 成员初始化列表 和 默认初始化 完成之后才执行的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <iostream> class MyClass { int a = 5; // 声明时直接初始化 int b; // 没有默认值 int c; public: MyClass(int x) : b(x), c(b + 1) { std::cout << "Constructor body: a = " << a << ", b = " << b << ", c = " << c << std::endl; a = 10; // 构造函数体内修改 } void print() { std::cout << "Final values: a = " << a << ", b = " << b << ", c = " << c << std::endl; } }; int main() { MyClass obj(20); obj.print(); return 0; } |
1 2 |
Constructor body: a = 5, b = 20, c = 21 Final values: a = 10, b = 20, c = 21 |
其他问题
静态成员变量和全局成员变量谁先初始化
- 在同一个编译单元中,静态变量和全局变量的初始化顺序是按照它们的定义顺序来的,不区分它们是全局变量还是静态变量
- 两者都属于 静态存储期变量
声明时直接初始化为何位于成员初始化列表之后,构造函数内部代码之前
- 声明时直接初始化的行为
- 在
C++
中,声明时直接初始化 的初始值实际上是默认初始化值 - 如果该成员没有在 成员初始化列表 中显式提供初始化值,编译器会使用默认初始化值
- 在
- 位置原因
- 成员初始化列表 是为所有类成员提供显式初始化的地方,初始化的顺序严格按照成员在类中声明的顺序
- 如果某个成员变量没有在成员初始化列表中显式初始化,而在类声明中提供了默认初始值
那么编译器会将这部分初始化代码插入到构造函数中,位于构造函数内部代码执行之前
- 构造函数代码执行顺序
- 构造函数内部代码的执行始终发生在 所有成员变量初始化完成之后
对声明时直接初始化的理解
- 声明时直接初始化的代码,本质是改变目标对象的默认值
1 2 3 4 5 6 7 |
class A { int a = 10; int b; public: A() : a(20) { std::cout << a << std::endl; } }; |
- 当初始化列表里面没有对这个变量初始化时,编译器才会生成汇编代码并插入到构造函数里面
- 有的话,就不会有生成汇编并插入
- 之所以声明时直接初始化,它的初始化顺序要位于初始化列表之后,是因为在初始化列表里面没有对声明时直接初始化的对象进行初始化时,
它需要在构造函数里面插入相关汇编 - 之所以声明时直接初始化,它的初始化顺序要位于构造函数内部代码之前,是因为要保证构造函数内部代码的执行始终发生在 所有成员变量初始化完成之后
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Deelx正则引擎使用12/24
- ♥ 深度探索C++对象模型一02/09
- ♥ C++11_第四篇12/08
- ♥ C++_多态、类型转换、数据段、BSS段、类型视图06/21
- ♥ STL_slist08/28
- ♥ Soui九07/25