c++ - 内联变量仿真 : can I use global static references to enforce the initialization order of static variable in functions?

标签 c++ initialization global-variables inline

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 文件使用 ab .没有其他使用 a_initb_init .

我认为:

  1. a must be initialized before b , 在每个包含 b 的翻译单元中;
  2. 因为没有别的调用b_init , b_init仅在初始化时调用 b .从当时的1 a必须已经初始化(a_init 必须返回);
  3. a_obj is initialized when a_init is called , b_obj 也是对于 b_init ;
  4. 结合 2 和 3,a_obja在调用 b_init 之前初始化,因此 use(a)是安全的,初始化顺序必须是A() < B() (返回 A(),然后调用 B());
  5. 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/

相关文章:

c++ - 是否可以在模板化函数签名中使用 typedef?

c++ - 在c++中编写初始化类

c++ - `a?b:c` 的操作数可以有不同的类型吗?最好的选择是什么?

c++ - 全局范围与文件范围

c++ - 在 C++ 中生成包含负范围的随机数

c++ - 关于 COM Release() 方法的问题

c++ - 在 OpenSceneGraph 中实现对象在平面上的搜索行为?

c++ - gcc:缺少有关构造函数中初始化顺序的警告

c - 更新全局结构体的成员

python - 需要帮助修复我用 Python 制作的游戏