何时初始化静态和全局变量?

Zac*_*ary 36 c++ static initialization global-variables

C++我知道staticglobal对象之前构造main函数.但是如你所知,之前C没有这种类型.initialization proceduremain

例如,在我的代码中:

int global_int1 = 5;
int global_int2;
static int static_int1 = 4;
static int static_int2;
Run Code Online (Sandbox Code Playgroud)
  • 这四个变量何时初始化
  • 在编译期间初始化值54存储的位置?初始化时如何管理它们?

编辑:
澄清第二个问题.

  • 在我的代码使用5初始化 global_int1,这样怎么能编译器分配 5global_int?例如,编译器可能首先将5值存储在某处(即表),并在初始化开始时获取此值.
  • 至于"如何在初始化时管理它们?",它真的很模糊,我自己也不知道如何解释.有时候,解释一个问题并不容易.忽略它,因为我还没有完全掌握这个问题.

Jam*_*nze 23

通过静态和全局对象,我假设您指的是在命名空间范围内定义的具有静态生命周期的对象.当使用局部范围定义此类对象时,规则略有不同.

形式上,C++在三个阶段初始化这些变量:1.零初始化2.静态初始化3.动态初始化语言还区分需要动态初始化的变量和需要静态初始化的变量:所有静态对象(具有静态生命周期的对象)是首先将零初始化,然后初始化具有静态初始化的对象,然后进行动态初始化.

作为简单的第一近似,动态初始化意味着必须执行某些代码; 通常,静态初始化不会.从而:

extern int f();

int g1 = 42;    //  static initialization
int g2 = f();   //  dynamic initialization
Run Code Online (Sandbox Code Playgroud)

另一个近似是静态初始化是C支持的(对于具有静态生命周期的变量),动态的一切.

编译器如何执行此操作当然取决于初始化,但在基于磁盘的系统上,可执行文件从磁盘加载到内存中,静态初始化的值是磁盘上映像的一部分,并由系统直接加载磁盘.在传统的Unix系统中,全局变量将分为三个"段":

文本:
代码,加载到写保护区域.带有`const`类型的静态变量也将放在这里.
数据:
静态变量与静态初始化器.
BSS:
具有无初始化程序(C和C++)或动态初始化(C++)的静态变量.可执行文件不包含该段的图像,系统在启动代码之前只将其全部设置为"0".

我怀疑很多现代系统仍然使用类似的东西.

编辑:

还有一句话:上面提到的是C++ 03.对于现有程序,C++ 11可能不会改变任何东西,但它确实添加constexpr(这意味着一些用户定义的函数仍然可以是静态初始化)和线程局部变量,这会打开一整套新的蠕虫.


Ker*_* SB 15

前言:"静态"一词在C++中有很多不同的含义.不要混淆.

所有对象都有静态存储持续时间.那是因为它们既不是自动的,也不是动态的.(也不是线程本地的,虽然线程本地有点像静态.)

在C++中,静态对象初始化为两个阶段:静态初始化和动态初始化.

  • 动态初始化需要执行实际代码,因此对于以构造函数调用开头的对象,或者初始化程序是只能在运行时进行求值的表达式,会发生这种情况.

  • 静态初始化是指静态地知道初始化程序并且不需要运行构造函数.(静态初始化是零初始化常量初始化.)对于int具有常量初始化程序的变量,情况就是如此,并且保证这些变量在静态阶段确实已初始化.

  • (在发生任何其他情况之前,具有动态初始化的静态存储变量也会静态地进行零初始化.)

关键的一点是,静态初始化阶段根本不会"运行".数据从一开始就存在.这意味着没有"排序"或任何其他涉及静态初始化的动态属性.如果愿意,初始值将硬编码到程序二进制文件中.


Mik*_*our 5

这四个变量什么时候初始化?

如您所说,这发生在程序启动之前,即main开始之前。C没有进一步指定;在C ++中,这些发生在静态初始化阶段之前,而对象具有更复杂的构造函数或初始化程序。

在编译期间将初始化值(如5和4)存储在哪里?

通常,非零值存储在程序文件的数据段中,而零值存储在bss段中,该段仅为变量保留了足够的内存。程序启动时,数据段被加载到内存中,而bss段被设置为零。(当然,语言标准没有对此进行指定,因此编译器可以做其他事情,例如在运行之前生成代码以初始化每个变量main)。