混合内联和构造函数初始化的初始化顺序

Som*_*ude 3 c++ initialization language-lawyer

【这个问题源于这个问题

考虑以下程序:

#include <iostream>

struct Foo
{
    const size_t size;
    int* arr{ create_arr(size) };

    Foo(size_t s)
        : size{ set_size(s) }
    {
    }

    static int* create_arr(size_t s)
    {
        std::cout << "Creating array with size " << s << '\n';
        return new int[s];
    }

    static size_t set_size(size_t s)
    {
        std::cout << "Setting size to " << s << '\n';
        return s;
    }
};

int main()
{
    Foo f(10);
}
Run Code Online (Sandbox Code Playgroud)

的内联初始化arr取决于 的值size。但是 的值size仅在构造函数初始化列表中初始化。

GCC和Clang的正确处理它,而如果申报顺序会抱怨sizearr被镜像。我还听说 MSVC 会做“正确”的事情(根据另一个问题中的评论)。

我的问题是:这是明确定义的吗?

我知道初始化是按声明顺序完成的,但它是否也包括内联初始化?

Sec*_*ndi 5

我知道初始化是按声明顺序完成的,但它是否也包括内联初始化?

是的,它必须,请参阅class.base.init

13 在非委托构造函数中,初始化按以下顺序进行: (13.1) — 首先,并且仅对于最派生类 (4.5) 的构造函数,虚拟基类按照它们出现在深度优先上的顺序进行初始化从左到右遍历基类的有向无环图,其中“从左到右”是基类在派生类 base-specifier-list 中的出现顺序。(13.2) — 然后,直接基类按照它们出现在基说明符列表中的声明顺序进行初始化(不管内存初始化器的顺序如何)。(13.3) —然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样与 mem 初始化程序的顺序无关). (13.4) — 最后,执行构造函数体的复合语句。[注:声明顺序是为了保证base和member sub

虽然这里的标准不是很具体,但这应该是完全足够的,因为默认成员初始化器是初始化器。类定义中的顺序始终是这里的基础。在初始化方面,这里有一个例外与标准的许多其他部分非常矛盾。

在本节中还有一个附加说明,该标准通过对破坏的关注强调:

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

所以这里根本没有进一步解释的余地​​。