我特意创建了下面的代码,以方便地呈现问题。
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
)。