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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类初始化与构造函数初始化列表的顺序相关的知识,希望对你有一定的参考价值。

我想在类中初始化一堆成员以保持源文件更清晰。但是,对象采用我只通过构造函数接收的参数,并且可以通过赋值在构造函数初始化列表或构造函数中初始化。 (第二种选择肯定不会起作用。)这基本上是这样的情景:

在标题中

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时,此代码才有效。

答案

这一点得到了标准的保证,即非静态数据成员将按照类定义中的声明顺序进行初始化。它们如何初始化(通过默认成员初始化程序或成员初始化程序列表)以及这些初始化程序的顺序无关紧要。

[class.base.init]#13.3

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

[注意:声明顺序的作用是确保以初始化的相反顺序销毁基础和成员子对象。 - 结束说明]

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

另一答案

类定义中的顺序很重要,并指示初始化的顺序。除了重新定义你的课程(即交换订单)之外,没有办法逃避这个订单。

一旦进入构造函数体,就可以将任何非const成员变量的值赋值为您想要的任何值,但是这一点已经初始化了。如果你想在那之前初始化一个成员,你必须在构造函数体之前完成它 - 即使用Foo::Foo(Pointer * ptr) : ptr(ptr) {}或者像使用m1m2一样初始化它们。

另一答案

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

以上是关于类初始化与构造函数初始化列表的顺序的主要内容,如果未能解决你的问题,请参考以下文章

静态代码块构造代码块构造函数以及Java类初始化顺序

java学习之静态块显示初始化块构造函数this在构造函数中的调用,区别联系与调用顺序

继承中的构造析构函数调用顺序

成员对象和封闭类

Dart类(构造函数、单例)

C++类和对象下