类内初始化与构造函数初始化列表的顺序

时间:2018-09-07 10:37:53

标签: c++ initialization initialization-list operator-precedence in-class-initialization

我想在类中初始化一堆成员,以保持源文件的整洁。但是,这些对象采用仅通过构造函数接收的参数,并且可以在构造函数初始化列表中或通过赋值在构造函数中进行初始化。 (第二个选项肯定不起作用。)基本上是这种情况:

标题内

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之间的初始化顺序?显然,只有在ptrm1之前初始化m2时,此代码才有效。

3 个答案:

答案 0 :(得分:5)

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

[class.base.init]#13.3

  

(13.3)-然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样,无论mem-initializer的顺序如何)。

     

[注:声明顺序的执行必须确保以相反的初始化顺序销毁基础和成员子对象。 —尾注]

这意味着,初始化顺序将始终为ptr-> m1-> m2

答案 1 :(得分:1)

类定义中的顺序很重要,它指示初始化的顺序。除了重新定义您的课程(即在周围交换顺序)之外,没有其他方法可以逃脱该顺序。

一旦进入了构造函数主体,就可以分配任何具有所需值的非常量成员变量的值,但是那一点,它们已经被初始化了。如果要在此之前初始化成员,则必须在构造函数主体之前进行初始化-即使用Foo::Foo(Pointer * ptr) : ptr(ptr) {}或通过与m1m2一样初始化它们。 / p>

答案 2 :(得分:0)

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