C++ 用于初始化全局变量的函数何时执行?
在我程序中某些文件的顶部,在所有函数之外,我有以下变量:C++ 用于初始化全局变量的函数何时执行?,c++,C++,在我程序中某些文件的顶部,在所有函数之外,我有以下变量: namespace { int foo = foo_func(); } int bar = bar_func(); 正如您所知,foo只是该文件的一个局部变量,但每个文件都可以访问bar …但问题是:函数foo_func()和bar_func()何时实际运行?这是在运行main()之前发生的,还是可能在以后某个时间发生的(比如在实际需要这些值之前)?语言规范规定,在调用该翻译单元中的任何函数或访问该翻译单元中定义的任何对象之前,将
namespace {
int foo = foo_func();
}
int bar = bar_func();
正如您所知,foo
只是该文件的一个局部变量,但每个文件都可以访问bar
…但问题是:函数
foo_func()
和bar_func()
何时实际运行?这是在运行main()
之前发生的,还是可能在以后某个时间发生的(比如在实际需要这些值之前)?语言规范规定,在调用该翻译单元中的任何函数或访问该翻译单元中定义的任何对象之前,将执行初始化函数。所以,在一般情况下,这实际上取决于你们的定义是如何在翻译单元中传播的
初始化是按从上到下的顺序执行的,因此,根据您的定义顺序,bar_func
应该看到已经初始化的foo
,但是foo_func
应该看到“未初始化”(即零初始化)bar
请注意,如果您的main
驻留在另一个翻译单元中,这意味着不必在main()
之前进行初始化。但是,如果您试图从main
(或从其他任何地方)访问foo
或bar
,则应确保为定义这些变量的整个翻译单元触发初始化过程
此外,如果初始值设定项是常量表达式(
constexpr
函数),则整个初始化可以静态执行,这通常意味着变量将在已初始化(编译时初始化)的时间内开始其生命周期状态。使用非constexpr
函数的返回值初始化是动态初始化。动态初始化的顺序定义如下(省略一些我认为与您的问题无关的细节):
§3.6.2/2:
具有静态存储持续时间(3.7.1)或线程存储持续时间(3.7.2)的变量应在进行任何其他初始化之前进行零初始化(8.5)
[……]
在单个翻译单元中定义了有序初始化的变量应按照其在翻译单元中定义的顺序进行初始化。如果一个程序启动一个线程(30.3),则随后的变量初始化相对于在不同转换单元中定义的变量初始化是不顺序的。否则,变量的初始化相对于在不同转换单元中定义的变量的初始化被不确定地排序
§3.6.2/3:
允许实现将具有静态存储持续时间的非局部变量的初始化作为静态初始化来执行,即使这种初始化不需要静态完成,只要[Jerry的总结:它产生的结果与动态完成的结果相同。]
§3.6.2/4:
具有静态存储持续时间的非局部变量的动态初始化是否在main的第一个语句之前完成是由实现定义的。如果初始化延迟到main的第一条语句之后的某个时间点,则应在首次odr使用(3.2)与待初始化变量定义在同一转换单元中的任何函数或变量之前进行
这是头球吗?源文件?定义了
main()
的同一个文件?@pst:不,不能是(除非您遇到“静态初始化失败”)。尝试访问bar
将保证调用初始化函数,如上所述。如果从main
内部访问,则不会。请注意Andrey的文字:“在该翻译单元中定义的任何对象都被访问”,并且由于bar
是在该翻译单元中定义的对象,从main
访问它意味着在访问之前它已经被初始化。作为初始值设定项的常量表达式是不够的,您需要constepr
变量。