e.J*_*mes 20 c++ compiler-construction static initialization
我对函数中静态变量的底层实现感到好奇.
如果我声明一个基本类型的静态变量(char,int,double等),并给它一个初始值,我想编译器只是在main()调用之前在程序的最开始设置该变量的值.:
void SomeFunction();
int main(int argCount, char ** argList)
{
// at this point, the memory reserved for 'answer'
// already contains the value of 42
SomeFunction();
}
void SomeFunction()
{
static int answer = 42;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果静态变量是类的实例:
class MyClass
{
//...
};
void SomeFunction();
int main(int argCount, char ** argList)
{
SomeFunction();
}
void SomeFunction()
{
static MyClass myVar;
}
Run Code Online (Sandbox Code Playgroud)
我知道直到第一次调用该函数时才会初始化它.由于编译器无法知道第一次调用函数的时间,它是如何产生这种行为的?它本质上是在函数体中引入if块吗?
static bool initialized = 0;
if (!initialized)
{
// construct myVar
initialized = 1;
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*urr 12
在我看到的编译器输出中,函数局部静态变量完全按照您的想象进行初始化.
请注意,通常这不是以线程安全的方式完成的.因此,如果您具有可能从多个线程调用的静态本地函数,则应考虑到这一点.在调用任何其他函数之前在主线程中调用一次函数通常可以解决问题.
我应该补充说,如果本地静态的初始化是一个简单的常量,就像在你的例子中一样,编译器不需要经历这些旋转 - 它可以只是初始化图像中的变量,或者main()像常规的静态初始化一样(因为你的程序无法区分).但是如果用函数的返回值初始化它,那么编译器几乎必须测试一个标志,指示初始化是否已完成或等效.
Jam*_*kin 11
这个问题涉及类似的问题,但未提及线程安全性.对于它的价值,C++ 0x将使函数静态初始化线程安全.
(参见关于函数静态的C++ 0x FCD,6.7/4:"如果控件在初始化变量时同时进入声明,则并发执行应等待初始化完成.")
另外一个没有提到的是函数静态以它们构造的相反顺序被破坏,因此编译器维护一个在关闭时调用的析构函数列表(这可能与atexit使用的列表相同或不同).