具有静态存储持续时间的常量初始化变量的初始化顺序
Initialization order of constant initialized variable with static storage duration
基于以下代码片段:
const int a = 42;
const int b = a;
我们知道常量初始化是针对这两个变量执行的,常量初始化是静态初始化。
由于静态初始化的顺序是未指定的(与动态初始化不同,动态初始化指定了其顺序(,这是否可能导致未定义的行为,就好像b
的静态初始化发生在a
之前,它将读取未初始化的内存?
首先,让我们澄清上下文:我们正在考虑初始化具有静态存储持续时间的变量。此初始化实际上由两部分组成:静态阶段和动态阶段。静态阶段首先发生,在此阶段中变量之间没有依赖关系。初始化顺序仅对具有静态存储的变量的动态初始化很重要。
静态变量的(动态(初始化顺序通常并非未指定。它通常在单独的翻译单元之间未指定,在某些情况下在单个 TU 中也是如此。
const int a = dynamic_init();
const int b = a;
如果这些变量位于单个 TU 中,就像从示例中看起来的那样,则指定顺序:首先声明a
,因此首先初始化。
const int a = 42;
const int b = a;
42 是一个常量表达式。因此,a
具有常量初始化,即静态初始化(非动态(。因此,初始化顺序对于此变量无关紧要。
a
也是一个常量表达式,因为a
是具有静态存储和常量初始化器的const
变量。因此b
也具有非动态初始化。 因此,初始化顺序对于此变量无关紧要。
排除上下文:
由于静态初始化的顺序是未指定的 [...],这是否可能导致未定义的行为,就好像 b 的静态初始化发生在
仅仅因为标准没有指定顺序,并不意味着实现可以做任何它想做的事情。标准表示静态初始化发生,实现负责执行它。它必须选择按指定工作的订单。
实际上,顺序无关紧要,因为它对程序是不可观察的。 无论实现如何选择实现,这两个变量都初始化为 42。
由 [intro.execution] 指定
这两个声明的完整表达式分别是它们的 init 声明符。根据 [介绍执行#5]
全表情是。
- 初始化声明符 ([dcl.decl]( 或 mem 初始值设定项 ([class.base.init](,包括初始值设定项的构成表达式。
关联的初始化被视为其完整表达式的一部分
对于初始值设定项,执行实体的初始化(包括计算聚合的默认成员初始值设定项(也被视为完整表达式的一部分。
因此,它们的评估顺序由以下定义:
与全表达式相关的每个值计算和副作用在与要评估的下一个全表达式相关的每个值计算和副作用之前进行排序。
- 无法在声明时使用初始值设定项列表初始化常量字符*/字符串数组的向量
- 初始化常量字符* 数组
- 为什么MSVC14允许声明指向动态未初始化常量对象的指针
- C++初始化常量
- 在可变参数构造函数中初始化常量数组
- 使用数字初始化常量引用
- 如何在不初始化常量的情况下声明数组?
- 初始化常量静态 std::map unique_ptr作为值
- 为什么您可以初始化常量引用,但不能初始化来自右值的非常量引用
- 类中的初始化常量
- 如何初始化常量 CLSID
- 在类中初始化常量数组
- 在声明C++之后初始化常量变量
- C++初始化:常量全局与静态类成员的顺序
- 在头文件中声明并初始化常量
- 恒常性添加无效?错误:无法使用字符**初始化常量字符**
- 为什么我能够在构造函数中初始化常量
- 通过指针初始化常量矩阵<双精度,0,80>(来自 Dlib)
- C++构造函数:初始化常量引用时出现垃圾
- 用自身初始化C++常量变量