非静态/静态/全局/子类成员的初始化顺序
Initialization order for nonstatic/static/global/subclass members
我特意创建了下面的代码,以方便地呈现问题。
Question>所有变量的初始化顺序是什么?
#include <iostream>
int iGlobal = 10;
class A {
public:
A(int _a) : m_a_a(_a) {}
private:
int m_a_a;
};
class B : public A
{
public:
B() : m_b_b(40), A(20), m_b_a(30) {}
private:
static int m_b_static_a;
int m_b_a;
int m_b_b;
int m_b_c; // this variable is NOT initialized in the B::B() initialization list
static int m_b_static_b;
};
int B::m_b_static_a = 11;
int B::m_b_static_b = 12;
int main(void)
{
B b;
return 0;
}
首先,我列出所有变量如下:
iGlobal, m_a_a, m_b_static_a, m_b_a, m_b_b, m_b_c, m_b_static_b
我认为我是对的。
m_a_a < m_b_a < m_b_b < m_b_c (i.e. X < Y iff X is initialized early than Y)
m_b_static_a < m_b_static_b
Rule1> c++保证编译单元(.cpp文件)中的变量按声明顺序初始化。
Rule2>在初始化列表中列出的顺序不控制初始化的顺序。
我在全局变量,静态变量和非静态变量之间排序有问题
在编译单元内,全局变量的初始化顺序与声明顺序相同。然而,不同编译单元之间的顺序是未指定的(参见什么是"静态初始化顺序惨败"?)。
类初始化顺序:
- 基类的成员(当存在继承时)
- 当前类的成员 构造函数
成员初始化遵循声明顺序,无论初始化列表中使用的顺序如何。
有class C : public A, public B
,初始化A
,然后是B
,然后是C
。它们的破坏顺序是相反的。
:虚基类不尊重上述顺序。
引用c++ 03标准§12.6.2/5:
初始化应按以下顺序进行:
-首先,并且仅用于最派生类as的构造函数类中初始化虚基类的从左到右遍历中出现的顺序为深度优先基类的有向无环图,其中"从左到右"是基类名称在派生类中的出现顺序base-specifier-list .
-那么,直接基类应按声明顺序初始化当它们出现在基本指定符列表中时(无论它们的顺序如何)mem-initializers)。
—则非静态数据成员应按其初始化顺序初始化是在类定义中声明的(还是不管顺序如何)
——最后,执行构造函数体。
总结,顺序为:
iGlobal (global)
B::m_b_static_a (static)
B::m_b_static_b (static)
A::m_a_a (base class member)
B::m_b_a (class member)
B::m_b_b (class member)
不,所有的"全局变量"将在main
:
iGlobal, m_b_static_a, m_b_static_b, m_a_a, m_b_a, m_b_b
和m_b_c
从未初始化。
规范初始化顺序为:
- 基类从左到右
- 非静态数据成员从上到下
- 构造函数体
下面是我在vc++ 2005中观察到的初始化顺序:
- 全局数据(
iGlobal
== 10进入main()
前) -
静态数据成员(
B::m_b_static_a
== 11,B::m_b_static_b
== 12) - 基类(
A::m_a_a
== 20) - 初始化列表中的非静态数据成员 (
B::m_b_a
== 30,B::m_b_b
== 40)
B::m_b_c
从B的构造函数返回后保持未初始化(设置为0xcccccccc
)。
- 使用g++静态初始化带有命名标签的嵌套C++结构
- 静态初始化的反义词是什么?
- 在静态初始化期间运行代码
- 结构数组的嵌入式C++静态初始化
- 初始化与类类型相同的静态成员(静态初始化顺序问题)
- 使用 constexpr 和 std::array 进行静态初始化来替换动态初始化的 std::vector 的闰年
- MSVC 2017 在单个翻译单元中违反静态初始化顺序
- VC++6 线程安全静态初始化
- 具有必要副作用的静态初始化被优化掉了
- 未使用全球的静态初始化器
- w/ w/结构带char缓冲液的静态初始化[]
- 静态初始化的对象不能放在块中尝试
- 功能指针的静态初始化
- lambda(或函数)C++中的静态初始化
- C++静态初始化顺序:添加到映射中
- 复杂类型数组的静态初始化
- C++ - 在派生类中静态初始化受基类保护的成员变量
- 静态初始化插件工厂
- 静态初始化包含功能指针的对象的constexpr std ::数组
- 找出静态初始化是否结束