【问题标题】:c++ initialization static variable in "local scope"c ++在“本地范围”中初始化静态变量
【发布时间】:2020-02-07 23:51:37
【问题描述】:

静态变量在程序开始时初始化,如here中所述,静态变量的初始化顺序是未定义的。因此,用另一个静态变量初始化一个静态变量可能会导致程序崩溃。

在函数中声明的“本地”静态变量也是如此吗?

使用全局声明的静态变量来初始化“本地”静态变量是否安全?

如果我在同一个局部范围内有多个静态变量,使用早期声明的变量来初始化晚期声明的变量是否安全?

【问题讨论】:

  • 当执行到达该行时,会初始化动态初始化的局部静态变量
  • 所有不是用单个翻译单元定义的局部变量的静态存储持续时间变量都按照它们在翻译单元中定义的顺序创建和销毁。仅当您有多个翻译单元和静态存储持续时间变量取决于另一个翻译单元中的静态存储持续时间变量时,才会出现链接中描述的问题,因为您无法控制首先初始化哪个翻译单元。这不是函数中的静态变量的问题。一方面,该功能不能跨多个翻译单元拆分。
  • @user4581301 你的第一句话只适用于动态初始化。静态初始化首先发生,例如在文件范围 int a = foo(); int b = 5; int c = bar(); 中,b 在执行 foo 期间保证具有值 5
  • 谢谢,@M.M 我怀疑类似的事情(如果编译器知道该变量的内容,为什么不在编译时将其烧录?)但我找不到确认。现在我已经花了更多时间and found it 我对我提出的答案进行了一些修正。

标签: c++ compilation


【解决方案1】:

具有静态存储持续时间的变量,其中初始值在编译时已知,zero initializedconstant initialized 是静态初始化并在其他所有内容之前初始化(在 C++11 和更早的标准版本中,在常量初始化之前为零初始化)。毕竟,如果编译器和链接器在编译时确切地知道该变量的值是什么,他们为什么不把值放在那里呢?

静态初始化变量不是问题。如果您要分配一个常量或零,则该变量不依赖于其他任何东西。剩下的就是动态初始化,如果我正确地阅读了 C++ 标准中的 [basic.start.static],那么静态初始化都发生在任何 translation unit 中的任何动态初始化之前。问题在于动态初始化的变量与静态存储持续时间跨多个翻译单元交互。您可以保证翻译单元内的初始化顺序,按照定义的顺序,但您不能保证翻译单元的初始化顺序。

在函数中声明的“本地”静态变量也是如此吗?

没有。 static 局部变量具有明确定义的初始初始化顺序。动态初始化将在第一次使用时发生,它们不能跨翻译单元拆分,这消除了非本地初始化顺序的歧义。

如果我在同一个局部范围内有多个静态变量,使用早期声明的变量来初始化晚期声明的变量是否安全?

是的。同样,我们有一个明确定义的初始化顺序。动态初始化的变量将按顺序初始化,静态初始化的变量已经初始化。你可以用一个线程把它搞砸,但是 C++11 和更好地确保一个线程不能中断静态变量的初始化。如果一个线程在 两个 静态变量的初始化之间中断,这是否安全取决于你,但第一个变量仍会在第二个变量之前初始化。

使用全局声明的静态变量来初始化“本地”静态变量是否安全?

并非总是如此。在main 之前分配并初始化了一个非局部变量,因此通常在您有机会调用包含静态局部变量的函数之前,它们已被初始化并准备好使用。

但是如果使用包含依赖于来自不同翻译单元的变量的静态变量的函数进行初始化呢?

在A.cpp中说我们有

int A_variable  = something_dynamic();

在 B.cpp 中我们有

int  func()
{
    static int local_static = A_variable;
    return local_static;
}
int B_variable = func();

B_variable 的初始化可能发生在 A_variable 的初始化之前。这将调用func 并将local_static 设置为B_variable 中尚未定义的值。哎呀。

【讨论】:

    猜你喜欢
    • 2013-07-21
    • 2013-02-13
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2021-07-28
    • 1970-01-01
    • 2012-10-26
    相关资源
    最近更新 更多