C++全局变量初始化顺序

cor*_*zza 35 c++ variables initialization declaration definition

我不明白以下代码示例的作用以及它是如何做到的:

#include <stdio.h>

int f();

int a = f(); // a exists just to call f

int x = 22;

int f() {
    ++x;
    return 123; // unimportant arbitrary number
}

int main() {
    printf("%d\n", x);
}
Run Code Online (Sandbox Code Playgroud)

当它运行时它打印23,这是直观的答案.

但是在C++中,全局变量应该按照定义的顺序进行初始化.这意味着a之前应该初始化x,因为它是之前定义的x.如果是这种情况,则f必须在x初始化之前调用该函数,因为调用fa定义的一部分.

如果fx初始化之前确实被调用,那将意味着f会尝试增加x- 我不确定的结果(很可能是UB,或者某些乱码值).然后,在a初始化之后,x将初始化为22并且程序将打印出来22.

显然,这不是发生的事情.但是什么呢?该代码实际上做了什么?

它似乎x被设置为22a = f()被评估之前,但这意味着初始化的顺序是相反的(我可能也错误的是初始化是什么,或者什么时候发生).

Ker*_* SB 34

这个问题有点微妙; 有关详细信息,请参阅C++ 11 3.6.2.

对我们来说重要的是,"静态存储持续时间的非局部变量"(或通俗话说的"全局变量")有两个初始化阶段:静态初始化阶段动态初始化阶段.静态阶段首先出现.它看起来像这样:

int a = 0;
int x = 22;
Run Code Online (Sandbox Code Playgroud)

之后运行动态初始化:

a = f();
Run Code Online (Sandbox Code Playgroud)

关键是静态初始化根本不"运行" - 它只包含在编译时已知的设置值,因此在任何执行发生之前已经设置了这些值.初始化int x = 22;静态的原因是初始化器是一个常量表达式.


有些情况下可以将动态初始化提升到静态阶段(但不必),但这不是其中一种情况,因为它不符合要求

初始化的动态版本在初始化之前不会更改命名空间作用域的任何其他对象的值

当这种提升发生时,允许产生的初始值可以与不发生时不同.标准中有一个例子就是一个这样的"不确定"初始化.