我不明白下面的代码示例做什么以及它是如何做的:C++全局变量初始化顺序
#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);
}
当这样跑了打印23
,这是直观的答案。
但是在C++中,全局变量是supposed to be按定义顺序初始化。这意味着a
应在x
之前初始化,因为它在x
之前定义。如果是这种情况,那么函数f
必须在x
初始化之前调用,因为f
的调用是a
的定义的一部分。
如果f
x
初始化之前确实叫,这将意味着f
将设法增加x
- 其结果我真的不特定的(最有可能UB,或一些乱码值)。然后,a
初始化后,x
将被初始化为22
,程序将打印出22
。
很明显,这不是什么情况。但是,什么?代码实际上做了什么?
它肯定好像x
设置为22
a = f()
前计算,但是这将意味着初始化的顺序是相反的(我也可能是错的什么初始化,或者当它发生)。
所以基本上,初始化分为非副作用的一部分“运行”第一(无功能,只是汇编代码改变了内存并增加堆栈指针)以及第二个运行的副作用部分(在其中执行实际功能)。如果一个功能可以被证明没有副作用,那么它可以被升高到第一部分。我理解正确吗?有道理。另外,你写了'x = f();',但我认为你的意思是'a = f();'(这就是我的代码)。 – corazza
另外,你最后一段的第一句话有点奇怪:*当这种提升发生时,最终的初始值可能会不同,如果它没有发生。* - 你是什么意思?看起来你错过了一个“它”,但总的来说,你所描述的有点混乱,也许发布这个例子会有所帮助? – corazza
@yannbane:这个例子在我引用的部分。我不愿意开始复制它的大部分内容,因为你应该基本阅读它的全部内容。我建议你[转向github](https://github.com/cplusplus/draft),并为自己制作一份标准副本。是的,有两个阶段。第一阶段甚至不会“改变内存” - 初始值只是写入二进制文件并由加载程序加载到内存中。 –