具有静态存储持续时间的常量初始化变量的初始化顺序

Initialization order of constant initialized variable with static storage duration

本文关键字:初始化 常量 变量 顺序 持续时间 静态 存储      更新时间:2023-10-16

基于以下代码片段:

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](,包括初始值设定项的构成表达式。

关联的初始化被视为其完整表达式的一部分

对于初始值设定项

,执行实体的初始化(包括计算聚合的默认成员初始值设定项(也被视为完整表达式的一部分。

因此,它们的评估顺序由以下定义:

与全表达式相关的每个值计算和副作用在与

要评估的下一个全表达式相关的每个值计算和副作用之前进行排序