编译器是如何实现静态变量初始化的?

我对函数内静态变量的底层实现很好奇.

I'm curious about the underlying implementation of static variables within a function.

如果我声明一个基本类型(char、int、double 等)的静态变量,并给它一个初始值,我想编译器会在程序的最开始简单地设置该变量的值在 main() 被调用之前:

If I declare a static variable of a fundamental type (char, int, double, etc.), and give it an initial value, I imagine that the compiler simply sets the value of that variable at the very beginning of the program before main() is called:

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;
}

但是,如果静态变量是类的实例:

However, if the static variable is an instance of a class:

class MyClass
{
    //...
};

void SomeFunction();

int main(int argCount, char ** argList)
{
    SomeFunction();
}

void SomeFunction()
{
    static MyClass myVar;
}

我知道在第一次调用该函数之前它不会被初始化.由于编译器无法知道该函数何时会被第一次调用,它是如何产生这种行为的呢?它本质上是否在函数体中引入了一个 if 块?

I know that it will not be initialized until the first time that the function is called. Since the compiler has no way of knowing when the function will be called for the first time, how does it produce this behavior? Does it essentially introduce an if-block into the function body?

static bool initialized = 0;
if (!initialized)
{
    // construct myVar
    initialized = 1;
}

推荐答案

在我看到的编译器输出中,函数局部静态变量完全按照你的想象进行初始化.

In the compiler output I have seen, function local static variables are initialized exactly as you imagine.

请注意,通常这不是以线程安全的方式完成.因此,如果您的函数具有可能从多个线程调用的静态局部变量,则应考虑到这一点.在调用任何其他函数之前在主线程中调用一次该函数通常会奏效.

Note that in general this is not done in a thread-safe manner. So if you have functions with static locals like that that might be called from multiple threads, you should take this into account. Calling the function once in the main thread before any others are called will usually do the trick.

我应该补充一点,如果本地静态的初始化是通过一个简单的常量,比如你的例子,编译器不需要经历这些旋转――它可以只在图像中或在 之前初始化变量main() 就像一个常规的静态初始化(因为你的程序无法区分).但是如果你用一个函数的返回值来初始化它,那么编译器几乎必须测试一个标志,表明初始化是否已经完成或等价的东西.

I should add that if the initialization of the local static is by a simple constant like in your example, the compiler doesn't need to go through these gyrations - it can just initialize the variable in the image or before main() like a regular static initialization (because your program wouldn't be able to tell the difference). But if you initialize it with a function's return value, then the compiler pretty much has to test a flag indicating if the initialization has been done or something equivalent.

相关文章