N4424介绍 inline
变量(可以在多个翻译单元中定义的变量,在仅 header 库中很有用),但在 C++14 中不是。我一直在使用下面的方法来模拟它:
// a.hpp
#pragma once // to simplify
inline A& a_init() { static A a_obj; return a_obj; }
static A& a = a_init();
和
// b.hpp
#pragma once // to simplify
#include "a.hpp"
inline B& b_init() { static B b_obj{ use(a) }; return b_obj; }
static B& b = b_init();
cpp 文件使用 a
和 b
.没有其他使用 a_init
和 b_init
.
我认为:
-
a
must be initialized beforeb
, 在每个包含b
的翻译单元中; - 因为没有别的调用
b_init
,b_init
仅在初始化时调用b
.从当时的1a
必须已经初始化(a_init
必须返回); -
a_obj
is initialized whena_init
is called ,b_obj
也是对于b_init
; - 结合 2 和 3,
a_obj
和a
在调用b_init
之前初始化,因此use(a)
是安全的,初始化顺序必须是A() < B()
(返回A()
,然后调用B()
); - Destructors run in the reverse order of the completion of their construction , 所以
~B() < ~A()
.
我的推理正确吗?这是 inline A a; inline B b{ use(a) };
的工作仿真吗?并保证 A() < B() < ~B() < ~A()
的顺序?
最佳答案
在不同翻译单元(即.cpp 文件)中定义的静态变量的初始化顺序可以唤起所谓的static initialization order fiasco。 .
幸运的是,有一种方法可以使用 Construct On First Use Idiom 来防止这种惨败。 .你所做的很像那个成语。
关于您的情况:由于 header “b.hpp”在 b
的定义之前包含 header “a.hpp”。当在翻译单元中包含“b.hpp”时,“a.hpp”也将包含在内。预处理器将分别用 header “a.hpp”和“b.hpp”的代码替换 include 指令,因为 #include "a.hpp"
位于 b 的定义之上
,a
将在 b
之前定义,因为“在同一编译单元中,顺序定义明确(即与定义相同的顺序) ”。因此,您强制使用正确的定义顺序。
因此,您的推理成立。我不知道这是否是 inline A a 的有效模拟;内联 B b{ use(a) };
.
关于c++ - 内联变量仿真 : can I use global static references to enforce the initialization order of static variable in functions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33296007/