非静态/静态/全局/子类成员的初始化顺序

时间:2011-12-01 18:30:13

标签: c++

我故意创建以下代码,让我轻松提出问题。

问题>所有变量的初始化顺序是什么?

#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&GT; C ++保证编译单元(.cpp文件)中的变量按声明顺序初始化。

规则2&GT;初始化列表中列出的顺序不控制初始化的顺序。

我在全局变量,静态变量和非静态变量中排序有问题。

3 个答案:

答案 0 :(得分:4)

在编译单元中,全局变量的初始化顺序与它们声明的顺序相同。但是,订单在不同的编译单元中未指定(请参阅What's the "static initialization order fiasco"?)。

课程初始化顺序

  1. 基类的成员(存在继承时)
  2. 当前班级的成员
  3. 构造
  4. 成员初始化遵守声明顺序,无论初始化列表中使用的顺序如何。

    拥有class C : public A, public B,初始化A,然后B,然后C。它们的破坏以相反的顺序发生。

    注意:虚拟基类不遵守上述顺序。

    引用C ++ 03标准中的§12.6.2/ 5:

      

    初始化应按以下顺序进行:

         

    - 首先,仅适用于派生程度最高的类的构造函数   如下所述,虚拟基类应在中初始化   命令它们出现在深度优先从左到右的遍历中   基类的有向非循环图,其中“从左到右”是   派生类中基类名称的出现顺序   基说明符列表。

         

    - 然后,直接基类应按声明顺序初始化   因为它们出现在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)
    

答案 1 :(得分:2)

不,所有“全局”都将在main之前初始化:

iGlobal, m_b_static_a, m_b_static_b, m_a_a, m_b_a, m_b_bm_b_c永远不会被初始化。

答案 2 :(得分:0)

规范初始化顺序是:

  1. 基类从左到右
  2. 非静态数据成员自上而下
  3. 构造函数的主体
  4. 这是我在VC ++ 2005中观察到的初始化顺序:

    1. 输入iGlobal之前的全球数据(main() == 10)
    2. 静态数据成员(B::m_b_static_a == 11,B::m_b_static_b == 12)
    3. 基类(A::m_a_a == 20)
    4. 初始化列表中的非静态数据成员 B::m_b_a == 30,B::m_b_b == 40)
    5. 从B的构造函数返回后,

      B::m_b_c仍然未初始化(设置为0xcccccccc)。