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

新手上路,请多包涵

我很好奇函数中静态变量的底层实现。

如果我声明一个基本类型(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;
}

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

 class MyClass
{
    //...
};

void SomeFunction();

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

void SomeFunction()
{
    static MyClass myVar;
}

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

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

原文由 e.James 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 668
2 个回答

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

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

我应该补充一点,如果本地静态的初始化是通过像您的示例中那样的简单常量,编译器不需要经过这些回转 - 它可以只初始化图像中或之前的变量 main() 就像一个常规的静态初始化(因为你的程序无法区分)。但是,如果您使用函数的返回值对其进行初始化,那么编译器几乎必须测试一个标志,该标志指示是否已完成初始化或类似的操作。

原文由 Michael Burr 发布,翻译遵循 CC BY-SA 2.5 许可协议

这个问题 涵盖了类似的基础,但没有提到线程安全。对于它的价值,C++0x 将使函数静态初始化线程安全。

(参见 C++0x FCD , 6.74 关于函数静态:“如果控制在变量初始化时同时进入声明,则并发执行应等待初始化完成。”)

另一件没有提到的事情是函数静态以它们构造的相反顺序被破坏,因此编译器维护一个析构函数列表以在关闭时调用(这可能与 atexit 使用的列表相同,也可能不同)。

原文由 James Hopkin 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题