是否可以使用 C++17 内联成员强制跨 TU 的全局变量的初始化顺序?
Can initialization order of global variables across TUs be forced with C++17 inline members?
这主要是一个好奇心驱动的问题,我不打算写这样的代码。
这是 关于动态初始化顺序的跟进。
根据我在答案中给出的内容,内联静态成员变量按照它们 类 在源代码中出现的顺序进行初始化 if 这样的顺序在不同的地方是相同的它们都出现的所有翻译单元 (TU)。
此外,[basic.start.dynamic]-3.1 部分适用于偏序(其他内联静态)和有序变量。也就是同一个TU里的普通全局变量。
所以,给出这个例子:
//A.hpp
struct A{
inline static int a=foo();// Some function with possible side-effects
};
//B.hpp
struct B{
inline static int b=foo();
};
//X.cpp
int x1 = foo();
#include "A.hpp"
int x2 = foo();
#include "B.hpp"
int x3 = foo();
//Y.cpp
int y1 = foo();
#include "A.hpp"
int y2 = foo();
#include "B.hpp"
int y3 = foo();
变量是否按以下顺序初始化?
(x1,y1)
顺序未定,
a
,
(x2,y2)
顺序未定,
b
,
(x3,y3)
顺序未定。
此外,如果翻译单元只有 类 之一,规则是否仍然适用?
//Z.cpp
int z1 = foo(); // Initialized with (x1,y1) ?
#include "A.hpp"
int z2 = foo(); // Initialized with (x2,y2) or anytime later ?
特别是,包含 A::
是否会创建一个障碍,保证 z2
在 (x1,y1)
之后初始化?
结果:
g++ 10.1.0:
x1=1 a=2 x2=3 b=4 x3=5 y1=6 y2=7 y3=8 z1=9 z2=10
clang++ 10.0.0:
a=1 b=2 x1=3 x2=4 x3=5 y1=6 y2=7 y3=8 z1=9 z2=10
两个编译器至少对一组 x,y
变量打破了我的假设。我错过了什么?
我主要参考这个
If V and W have ordered initialization and the definition of V is appearance-ordered before the definition of W, or if V has partially-ordered initialization, W does not have unordered initialization, and for every definition E of W there exists a definition D of V such that D is appearance-ordered before E, then
我是不是看错了这一段?我不太确定 ors 和 ands。
让我们稍微简化一下您的示例,使其更易于理解:
// X.cpp
int x1 = foo();
inline int a = foo();
int x2 = foo();
// Y.cpp
int y1 = foo();
inline int a = foo();
int y2 = foo();
你的问题是x1
是否保证在y2
之前初始化,y1
是否保证在x2
之前初始化。
答案是否定的。正如我所解释的 动态初始化的部分排序规则的效果是,每个翻译单元的外部内联变量的“实例”在概念上被视为一个单独的变量;对象本身(只有一个)在第一次初始化时 任何 相应的名义变量都将被初始化。
例如,一个特定的排序会在 Y 翻译单元之前执行整个 X 翻译单元。在这种情况下,初始化的顺序是 x1
、a
、x2
、y1
(没有操作,因为 a
之前已初始化),y2
. (编译器同样可以在 X 中的所有内容之前对 Y 中的所有内容进行排序,或者将它们交错排列。)
引用的 [basic.start.dynamic]/3.1 来自比我在回答中考虑的更新版本的标准,但基本逻辑是相同的。让 V
= x1
和 W
= y2
。根据3.1,如果
,V
会在W
之前初始化
V
and W
have ordered initialization and the definition of V
is appearance-ordered before the definition of W
,
“或”
V
has partially-ordered initialization, W
does not have unordered initialization, and for every definition E
of W
there exists a definition D
of V
such that D
is appearance-ordered before E
不满足第一个条件,因为 V
不是 W
之前的 appearance-ordered。第二个条件也不满足,因为 V
和 W
每个只有一个定义,正如我所说,它们不是 appearance-ordered.
这主要是一个好奇心驱动的问题,我不打算写这样的代码。
这是
根据我在答案中给出的内容,内联静态成员变量按照它们 类 在源代码中出现的顺序进行初始化 if 这样的顺序在不同的地方是相同的它们都出现的所有翻译单元 (TU)。
此外,[basic.start.dynamic]-3.1 部分适用于偏序(其他内联静态)和有序变量。也就是同一个TU里的普通全局变量。
所以,给出这个例子:
//A.hpp
struct A{
inline static int a=foo();// Some function with possible side-effects
};
//B.hpp
struct B{
inline static int b=foo();
};
//X.cpp
int x1 = foo();
#include "A.hpp"
int x2 = foo();
#include "B.hpp"
int x3 = foo();
//Y.cpp
int y1 = foo();
#include "A.hpp"
int y2 = foo();
#include "B.hpp"
int y3 = foo();
变量是否按以下顺序初始化?
(x1,y1)
顺序未定,a
,(x2,y2)
顺序未定,b
,(x3,y3)
顺序未定。
此外,如果翻译单元只有 类 之一,规则是否仍然适用?
//Z.cpp
int z1 = foo(); // Initialized with (x1,y1) ?
#include "A.hpp"
int z2 = foo(); // Initialized with (x2,y2) or anytime later ?
特别是,包含 A::
是否会创建一个障碍,保证 z2
在 (x1,y1)
之后初始化?
结果:
g++ 10.1.0:
x1=1 a=2 x2=3 b=4 x3=5 y1=6 y2=7 y3=8 z1=9 z2=10
clang++ 10.0.0:
a=1 b=2 x1=3 x2=4 x3=5 y1=6 y2=7 y3=8 z1=9 z2=10
两个编译器至少对一组 x,y
变量打破了我的假设。我错过了什么?
我主要参考这个
If V and W have ordered initialization and the definition of V is appearance-ordered before the definition of W, or if V has partially-ordered initialization, W does not have unordered initialization, and for every definition E of W there exists a definition D of V such that D is appearance-ordered before E, then
我是不是看错了这一段?我不太确定 ors 和 ands。
让我们稍微简化一下您的示例,使其更易于理解:
// X.cpp
int x1 = foo();
inline int a = foo();
int x2 = foo();
// Y.cpp
int y1 = foo();
inline int a = foo();
int y2 = foo();
你的问题是x1
是否保证在y2
之前初始化,y1
是否保证在x2
之前初始化。
答案是否定的。正如我所解释的
例如,一个特定的排序会在 Y 翻译单元之前执行整个 X 翻译单元。在这种情况下,初始化的顺序是 x1
、a
、x2
、y1
(没有操作,因为 a
之前已初始化),y2
. (编译器同样可以在 X 中的所有内容之前对 Y 中的所有内容进行排序,或者将它们交错排列。)
引用的 [basic.start.dynamic]/3.1 来自比我在回答中考虑的更新版本的标准,但基本逻辑是相同的。让 V
= x1
和 W
= y2
。根据3.1,如果
V
会在W
之前初始化
V
andW
have ordered initialization and the definition ofV
is appearance-ordered before the definition ofW
,
“或”
V
has partially-ordered initialization,W
does not have unordered initialization, and for every definitionE
ofW
there exists a definitionD
ofV
such thatD
is appearance-ordered beforeE
不满足第一个条件,因为 V
不是 W
之前的 appearance-ordered。第二个条件也不满足,因为 V
和 W
每个只有一个定义,正如我所说,它们不是 appearance-ordered.