Here in cppref http://en.cppreference.com/w/cpp/language/initialization says,
如果非内联变量 (C++17 起) 的初始化推迟到主/线程函数的第一条语句之后进行,它发生在第一次 ODR 使用之前与要初始化的变量在同一转换单元中定义的具有静态/线程存储持续时间的任何变量。
随后给出了延迟动态初始化的示例:
// - File 1 -
#include "a.h"
#include "b.h"
B b;
A::A(){ b.Use(); }
// - File 2 -
#include "a.h"
A a;
// - File 3 -
#include "a.h"
#include "b.h"
extern A a;
extern B b;
int main() {
a.Use();
b.Use();
}
评论说:
If a
在第一个语句之后的某个时刻初始化main
(其中 odr-使用定义在File 1
,强制其动态初始化运行),然后b
将在 A::A 中使用之前进行初始化
为什么可以if情况发生?没有a.Use()
网上争议解决使用a
thus a
必须在该语句之前初始化吗?
我认为你被 C++ 中的事物顺序误导了。
翻译单元(TU = 一个 .cpp 文件及其标头)在 C++ 中没有顺序。它们可以按任何顺序编译,但也可以并行编译。唯一特殊的 TU 是包含main()
,但即使这样,也可以随时按顺序编译。
在每个翻译单元中,初始值设定项都有一个出现的顺序。这也是它们初始化的时间顺序,但可能与它们在内存中的顺序不同(如果确定的话 - 严格来说,C++ 并不强制执行)。这不会导致初始化程序的顺序across翻译单位。它does发生在执行该翻译单元的函数之前,因为这些函数可能依赖于初始化的对象。
翻译单元中的函数当然可以以任何顺序出现;它们的执行方式取决于您在其中写入的内容。
现在有一些事情施加了额外的排序限制。我知道您知道某些初始化程序甚至可以在之后运行main()
已开始。如果发生这种情况,普通规则仍然适用,即单个 TU 的初始化程序必须在该 TU 中的函数之前执行。
在这种情况下,TUfile1
保存(默认)初始值设定项b
,必须先运行A::A
在同一个 TU 中。正如您正确注意到的那样,a.Use
必须在初始化之后发生a
。这需要A::A
.
因此,我们有以下顺序关系(其中<
means precedes
)
b < A::A
A::A < a
a < a.Use
因此传递性地
b < a.Use
正如您所看到的,使用起来很安全a.c
in a.Use
因为订单A::A < a.Use
也成立。
You can遇到问题,如果你做A::A
取决于b
and B::B
取决于a
。如果引入循环依赖,则无论哪个对象先初始化,它总是依赖于尚未初始化的对象。不要那样做。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)