正如在标题中 - 程序如何知道,当第二次调用函数时,foo
已经初始化:
int getFoo()
{
static int foo = 30;
return foo;
}
int main()
{
getFoo();
getFoo();
}
我想知道,程序是否存储了一些关于哪些静态变量已经初始化的附加信息。
编辑: 我在这里找到答案: Why does initialization of local static objects use hidden guard flags? 就像我猜测的那样 - 大多数编译器存储了额外的“保护变量”。
看看[stmt.dcl]/4:
- 具有静态存储持续时间或线程存储持续时间的块范围变量的动态初始化在控制第一次通过其声明时执行;这样的变量在初始化完成后被认为是初始化的。如果通过抛出异常退出初始化,则初始化未完成,因此下次控制进入声明时将再次尝试初始化。如果控件在初始化变量时同时进入声明,则并发执行应等待初始化完成.94如果控件在初始化变量时以递归方式重新进入声明,则行为未定义。
你必须要小心。原始static
s在编译时初始化,因此在您的示例中,GetFoo
实际上只返回一个常量。
然而...
static
s初始化一个对象(或通过调用一个函数初始化一个原语)在第一次输入声明它们的作用域时执行所述初始化。
此外,从C ++ 11开始,这必须以线程安全的方式完成,这会生成大量额外的代码(虽然在第一次通过后没有太多的运行时开销),这可能是一个问题,比如说,微控制器代码大小通常很重要。
这是一个具体的例子:
#include <iostream>
struct X
{
X () { std::cout << "Initialising m\n"; m = 7; }
int m;
};
void init_x ()
{
static X x;
}
int main () {
std::cout << "main called\n";
init_x ();
std::cout << "init_x returned\n";
}
输出:
main called
Initialising m
init_x returned