标准是否保证初始化顺序?

Mur*_* VP 8 c++

在下面的代码片段中,d1的初始化程序是d2,它尚未构造(正确吗?),D的复制构造函数中的dj是否是未初始化的内存访问?

struct D
{
    int j;

    D(const D& d) { j = d.j; }
    D(int i) { j = i; }
};

struct A
{
    D d1, d2;
    A() : d2(2), d1(d2) {}
};
Run Code Online (Sandbox Code Playgroud)

C++标准的哪一部分讨论了数据成员的初始化顺序?

Gre*_*ill 11

我现在没有标准的方便,所以我不能引用该部分,但结构或类成员初始化总是按声明的顺序发生.构造函数初始化列表中提到成员的顺序不相关.

Gcc有一个警告-Wreorder,当订单不同时会发出警告:

       -Wreorder (C++ only)
           Warn when the order of member initializers given in the code does
           not match the order in which they must be executed.  For instance:

                   struct A {
                     int i;
                     int j;
                     A(): j (0), i (1) { }
                   };

           The compiler will rearrange the member initializers for i and j to
           match the declaration order of the members, emitting a warning to
           that effect.  This warning is enabled by -Wall.

  • 这样做的原因是事物以与构造它们相反的顺序被破坏.在析构函数之后,您无法更改成员被破坏的顺序,因此构造的顺序*必须*对应. (5认同)
  • 但是,您仍然可以参考之前初始化的成员,如下所述:http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.7 (2认同)

Jam*_*lis 11

C++标准(ISO/IEC 14882:2003 12.6.2/5,初始化基础和成员)说:

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

- 首先,仅对于如下所述的派生类最多的构造函数,虚拟基类应按它们出现在基类有向无环图的深度优先从左到右遍历的顺序进行初始化,其中" "从左到右"是派生类base-specifier-list中基类名称的出现顺序.

- 然后,直接基类应按声明顺序初始化,因为它们出现在base-specifier-list中(无论mem-initializers的顺序如何).

- 然后,非静态数据成员应按照它们在类定义中声明的顺序进行初始化(同样不管mem-initializers的顺序如何).

- 最后,执行构造函数的主体.

Bullet point 3保证非静态数据成员初始化的顺序.


Mar*_*ork 6

在您的示例中,它将失败:

struct A
{
    D d1, d2;    
    A() : d2(2), d1(d2) {}
};

d1: is initialised first as it is declared first.
d2: is then initialized.
Run Code Online (Sandbox Code Playgroud)

因此,初始化列表将使用对无效对象的引用来构造d1(d2).

这是使编译器警告级别尽可能高的一个原因.
另外强制它将所有警告报告为错误.