这两种情况的初始化顺序有什么区别吗?

问题描述 投票:0回答:1

考虑这个例子:

#include <iostream>
struct A {
    A() {
        std::cout<<"hello" << std::endl;
    }
};
inline A a;
int main() {
}

这个例子导致Clang 15下的程序段,改为

#include <iostream>
struct A {
    A() {
        std::cout<<"hello" << std::endl;
    }
};
static inline A a;
int main() {
}

此示例成功打印

hello
。在这两种情况下,说明符
static
,IMO,不应该影响
std::cout
和变量
a
的初始化顺序,它们的初始化顺序都是不确定的,对吧?

c++ language-lawyer
1个回答
0
投票

简而言之,您所看到的差异是可能的,但这纯粹是巧合。 使用

static
而不使用
inline
以确保安全;否则初始化顺序不可靠。

首先注意[basic.start.dynamic] p1:

如果变量是隐式或显式实例化的专门化,则具有静态存储持续时间的非块变量的动态初始化是无序的;如果变量是不是隐式或显式实例化的专门化的内联变量,则该变量是部分有序的,否则是已订购。

inline A
static inline A
都具有部分有序的初始化。

因为在任何一种情况下

#include <iostream>
都出现在
a
的声明之前,所以在这两种情况下,
std::cout
的初始化都是 appearance-ordered
a
之前,但仅在您的翻译单元中,而不是在标准库。

如果我们认为标准库可能有额外的TU(

std::cout
的定义所在),那么[basic.start.dynamic] p3.1不适用,因此
std::cout
的初始化不适用必然发生在
a
初始化之前。

适用的项目符号是 [basic.start.dynamic] p3.3:

否则,V [

std::cout
]和W [
a
]的初始化是不确定顺序的。

在这种情况下,

static
只是给出了变量的内部链接,这对措辞没有任何影响。 它解决您的问题纯属巧合。 另请注意,
static inline
对于变量来说基本上没有意义,您可以只使用
static
来代替。 在这种情况下,
std::cout
a
都已有序初始化,并且
std::cout
始终会在
a
之前初始化。

© www.soinside.com 2019 - 2024. All rights reserved.