关于c ++:什么时候初始化静态变量和全局变量?

When are static and global variables initialized?

C++中,我知道staticglobal对象是在main函数之前构造的。 但是您知道,在C中,在main之前没有这样的initialization procedure

例如,在我的代码中:

1
2
3
4
int global_int1 = 5;
int global_int2;
static int static_int1 = 4;
static int static_int2;
  • 这四个变量什么时候初始化?
  • 在编译过程中将54之类的初始化值存储在哪里? 初始化时如何管理它们?

编辑:
第二个问题的澄清。

  • 在我的代码中,我使用5初始化global_int1,那么编译器如何将5分配给global_int? 例如,也许编译器首先将5值存储在某个地方(即表),并在初始化开始时获取该值。
  • 关于"初始化时如何管理它们?",这确实很模糊,我本人还没有解释。 有时候,解释一个问题并不容易。 由于我尚未完全掌握该问题,因此请忽略它。


对于静态和全局对象,我假设您的意思是带有
在名称空间范围内定义的静态生存期。当这样的物体
是在本地范围内定义的,规则略有不同。

正式地,C ++分三个阶段初始化此类变量:
1.零初始化
2.静态初始化
3.动态初始化
该语言还区分了需要
动态初始化,以及需要静态初始化的
初始化:所有静态对象(带有静态对象
生命周期)首先是零初始化,然后是静态对象
初始化,然后动态初始化
发生。

作为简单的一阶近似,动态初始化意味着
必须执行一些代码;通常是静态的
初始化没有。从而:

1
2
3
4
extern int f();

int g1 = 42;    //  static initialization
int g2 = f();   //  dynamic initialization

另一个近似是静态初始化是
C支持什么(对于具有静态生存期的变量),动态
其他一切。

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

文本:

将代码加载到写保护区域中。静态的
类型为const的变量也将放在这里。

数据:

带有静态初始值设定项的静态变量。

bss:

静态变量,无需初始化(C和C ++)或动态
初始化(C ++)。可执行文件对此不包含任何图像
段,然后系统将其全部简单地设置为" 0"
启动您的代码。

我怀疑很多现代系统仍在使用某些东西
类似。

编辑:

补充说明:上面提到的是C ++ 03。对于现有
程序,C ++ 11可能不会改变任何东西,但确实会改变
添加constexpr(这意味着某些用户定义的函数
仍然可以是静态初始化)和线程局部变量,
这打开了一个全新的蠕虫罐头。


前言:"静态"一词在C ++中具有多种不同的含义。不要感到困惑。

您所有的对象都有静态的存储期限。那是因为它们既不是自动的也不是动态的。 (也不是线程本地的,尽管线程本地有点像静态的。)

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

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

  • 静态初始化是指静态知道初始化器且无需运行构造函数的情况。 (静态初始化是零初始化或常量初始化。)使用常量初始化程序的int变量就是这种情况,并且可以确保将这些变量确实在静态阶段进行初始化。

  • (具有动态初始化的静态存储变量在发生其他任何事情之前也会被静态初始化为零。)

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


When are these four variables initialized?

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

Where values for initialization like 5 and 4 are stored during compilation?

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


从标准释义:

所有没有动态存储持续时间,没有线程本地存储持续时间并且不是本地的变量都具有静态存储持续时间。换句话说,所有全局变量都具有静态存储持续时间。

具有动态初始化的静态对象不一定要在主函数的第一条语句之前创建。关于这些对象是在main的第一个语句之前创建,还是在与要初始化的静态变量相同的转换单元中首次使用的任何函数或变量的首次使用之前创建的实现,定义为实现。

因此,在您的代码中,global_int1和static_int1肯定在main中的第一条语句之前初始化,因为它们是静态初始化的。但是,global_int2和static_int2是动态初始化的,因此它们的初始化是根据我上面提到的规则定义的实现。

至于第二点,我不确定我理解你的意思。你能澄清一下吗?