In Class 初始化与构造函数初始化列表的顺序

Order of In Class Initialization versus Constructor Initialization List

我想初始化一堆成员in-class以保持源文件更干净。但是,objects 接受一个我仅通过构造函数接收的参数,并且可以在构造函数初始化列表中或通过赋值在构造函数中进行初始化。 (第二种方案肯定不行。)基本上是这样的场景:

在Header

class Foo
{

public:
    Foo(Pointer * ptr);

private:

    Pointer * ptr;
    Member m1{ptr, "SomeText"};
    Member m2{ptr, "SomeOtherText"};
}

在 CPP

Foo::Foo(Pointer*ptr) : 
    ptr(ptr) 
{
    // ...
}   

现在的问题是:标准是否说明了 ptrm1 / m2 之间的初始化顺序?显然,此代码仅在 ptrm1m2 之前初始化时才有效。

它是标准定义的。成员按照 class 内的声明顺序进行初始化,因此您的代码完全有效。潜在的危险是构造函数中的初始化顺序与成员顺序不一致 - 然后仍然按声明顺序初始化字段。

这是由标准保证的,非静态数据成员将按照它们在 class 定义中声明的顺序进行初始化。它们的初始化方式(通过默认成员初始化器或成员初始化器列表)以及这些初始化器的顺序无关紧要。

[class.base.init]#13.3

(13.3) - Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note ]

也就是说,初始化顺序总是ptr -> m1 -> m2.

class 定义中的顺序很重要,它决定了初始化的顺序。除了重新定义您的 class(即调换顺序)之外,没有办法逃避该顺序。

一旦进入构造函数主体,就可以分配任何非常量成员变量的值,具有您想要的任何值,但那一点,它们已经初始化。如果你想在此之前初始化一个成员,你必须在构造函数主体之前完成它——即使用 Foo::Foo(Pointer * ptr) : ptr(ptr) {} 或像使用 m1m2 一样初始化它们。