【问题标题】:Order of In Class Initialization versus Constructor Initialization List类内初始化顺序与构造函数初始化列表
【发布时间】:2018-09-07 10:37:53
【问题描述】:

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

在标题中

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之前初始化时才有效。

【问题讨论】:

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


    【解决方案1】:

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

    [class.base.init]#13.3

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

    [ 注意:声明顺序是为了确保基子对象和成员子对象以与初始化相反的顺序被销毁。 — 尾注 ]

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

    【讨论】:

    • 漂亮,这正是我正在寻找的参考。谢谢!
    【解决方案2】:

    类定义中的顺序很重要,它决定了初始化的顺序。除了重新定义你的类(即交换顺序)之外,没有办法逃避这个顺序。

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

    【讨论】:

    • 您不能在 C++ 中重新定义变量。不过,您可以分配给他们。
    • @LightnessRacesinOrbit 谢谢——现在应该更好了。
    • 是的,是奈斯
    • 遗憾的是,这并不能真正回答问题,但它仍然包含准确的信息
    • @LightnessRacesinOrbit 它没有。我想对您的答案发表评论,但由于它比您的答案更长,我决定将其作为答案发布。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2012-03-19
      • 2021-06-12
      • 2010-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多