在C++
中,我知道static
和global
对象是在main
函数之前构造的。但正如你所知,在C
中,在main
之前没有这样的initialization procedure
。
例如,在我的代码中:
int global_int1 = 5;
int global_int2;
static int static_int1 = 4;
static int static_int2;
- 这四个变量何时初始化
5
和4
等初始化值在编译过程中存储在哪里?初始化时如何管理它们
编辑:
澄清第二个问题。
- 在我的代码中,我使用
5
来初始化global_int1
,那么编译器如何将5
分配给global_int
呢?例如,编译器可能首先将5
值存储在某个位置(即表),并在初始化开始时获取该值 - 至于"初始化时如何管理它们?",它真的很模糊,我自己还不知道如何解释。有时候,解释一个问题并不容易。由于我还没有完全掌握这个问题,所以请忽略它
我认为静态和全局对象是指具有在命名空间范围中定义的静态生存期。当这样的物体是用局部范围定义的,规则略有不同。
形式上,C++分三个阶段初始化这些变量:1.零初始化2.静态初始化3.动态初始化该语言还区分了需要动态初始化,以及那些需要静态的初始化:所有静态对象(具有静态的对象lifetime)首先初始化为零,然后使用static初始化,然后进行动态初始化发生。
作为一个简单的第一近似,动态初始化意味着必须执行某些代码;通常为静态初始化没有。因此:
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
变量,情况就是这样,您可以保证这些变量确实在静态阶段进行了初始化。 -
(具有动态初始化的静态存储变量也在发生任何其他事情之前静态初始化零。)
关键的一点是静态初始化阶段根本不会"运行"。数据从一开始就在那里。这意味着不存在"排序"或任何其他涉及静态初始化的动态属性。如果愿意的话,初始值会硬编码到程序二进制文件中。
这四个变量何时初始化?
正如您所说,这发生在程序启动之前,即main
开始之前。C没有进一步说明;在C++中,这些情况发生在静态初始化阶段具有更复杂构造函数或初始化器的对象之前。
在编译过程中,初始化值(如5和4)存储在哪里?
通常,非零值存储在程序文件的数据段中,而零值存储在bss段中,该段刚好为变量保留足够的内存。程序启动时,数据段加载到内存中,bss段设置为零。(当然,语言标准没有指定这一点,所以编译器可以做其他事情,比如在运行main
之前生成初始化每个变量的代码)。
标准释义:
所有不具有动态存储持续时间、不具有线程本地存储持续时间和非本地的变量都具有静态存储持续时间。换句话说,所有全局变量都有静态存储持续时间。
具有动态初始化的静态对象不一定要在主函数的第一条语句之前创建。实现定义了这些对象是在main中的第一条语句之前创建的,还是在首次使用与要初始化的静态变量在同一转换单元中定义的任何函数或变量之前创建的。
因此,在您的代码中,global_int1和static_int1肯定是在main中的第一条语句之前初始化的,因为它们是静态初始化的。然而,global_int2和static_int2是动态初始化的,因此它们的初始化是根据我上面提到的规则定义的。
至于你的第二点,我不确定我是否理解你的意思。你能澄清一下吗?