在C++
我知道static
和global
对象是在main
函数之前构建的。但正如您所知,在C
中,initialization procedure
之前没有这种main
。
例如,在我的代码中:
int global_int1 = 5;
int global_int2;
static int static_int1 = 4;
static int static_int2;
5
和4
等初始化值?如何在初始化时管理它们? 编辑:
澄清第二个问题。
5
来初始化 global_int1
,那么编译器如何将 5
分配给{{1} }}?例如,编译器可能首先将global_int
值存储在某处(即表),并在初始化开始时获取此值。答案 0 :(得分:23)
通过静态和全局对象,我认为你的意思是对象 命名空间范围内定义的静态生命当这样的对象 用本地范围定义,规则略有不同。
形式上,C ++在三个阶段初始化这些变量: 1.零初始化 2.静态初始化 3.动态初始化 该语言还区分了需要的变量 动态初始化,以及那些需要静态的 初始化:所有静态对象(具有静态的对象) life)首先初始化为零,然后是静态对象 初始化初始化,然后动态初始化 发生。
作为简单的第一近似,动态初始化意味着 必须执行一些代码;通常,静态 初始化没有。因此:
extern int f();
int g1 = 42; // static initialization
int g2 = f(); // dynamic initialization
另一个近似是静态初始化 C支持什么(对于具有静态生命周期的变量),动态 其他一切。
编译器如何做到这一点当然取决于 初始化,但在基于磁盘的系统上,可执行文件 从磁盘加载到内存中,静态值 初始化是磁盘上映像的一部分,并已加载 直接由系统从磁盘。在经典的Unix上 系统,全局变量将分为三个“段”:
我怀疑很多现代系统仍在使用某些东西 类似。
编辑:
另外一句话:上面提到的是C ++ 03。对于现有的
程序,C ++ 11可能不会改变任何东西,但确实如此
添加constexpr
(这意味着一些用户定义的函数
仍然可以是静态初始化)和线程局部变量,
这开辟了一整套新的蠕虫病毒。
答案 1 :(得分:12)
前言:“静态”一词在C ++中有很多不同的含义。不要混淆。
所有对象都有静态存储持续时间。那是因为它们既不是自动的,也不是动态的。 (也不是线程本地的,虽然线程本地有点像静态。)
在C ++中,Static对象分两个阶段初始化:静态初始化和动态初始化。
动态初始化需要执行实际代码,因此对于以构造函数调用开头的对象,或者初始化程序是只能在运行时进行求值的表达式,会发生这种情况。
静态初始化是指初始化程序是静态已知的,并且不需要运行构造函数。 (静态初始化是零初始化或常量初始化。)具有常量初始化程序的int
变量就是这种情况,并保证这些变量确实在静态阶段初始化。
(在发生任何其他事情之前,动态初始化的静态存储变量也静态零初始化。)
关键是静态初始化阶段根本不会“运行”。数据从一开始就存在。这意味着没有“排序”或任何其他涉及静态初始化的动态属性。如果您愿意,初始值将硬编码到程序二进制文件中。
答案 2 :(得分:3)
这四个变量何时初始化?
正如你所说,这发生在程序启动之前,即在main
开始之前。 C没有进一步说明;在C ++中,这些发生在静态初始化阶段在具有更复杂构造函数或初始化器的对象之前。
编译期间是否存储了像5和4这样的初始化值?
通常,非零值存储在程序文件的数据段中,而零值位于 bss 段中,该段仅为变量保留足够的内存。程序启动时,数据段将加载到内存中, bss 段将设置为零。 (当然,语言标准没有指定这一点,因此编译器可以执行其他操作,例如在运行main
之前生成代码以初始化每个变量。)
答案 3 :(得分:1)
从标准中解释:
所有没有动态存储持续时间,没有线程本地存储持续时间且不是本地存储的变量都具有静态存储持续时间。换句话说,所有全局变量都有静态存储持续时间。
具有动态初始化的静态对象不一定在main函数中的第一个语句之前创建。它是实现定义的,这些对象是在main中的第一个语句之前,还是在第一次使用与要初始化的静态变量相同的转换单元中定义的任何函数或变量之前创建的。
因此,在您的代码中,global_int1和static_int1肯定在main中的第一个语句之前初始化,因为它们是静态初始化的。但是,global_int2和static_int2是动态初始化的,因此它们的初始化是根据我上面提到的规则定义的实现。
至于你的第二点,我不确定我明白你的意思。你能澄清一下吗?