在C / C ++中,为什么将全局变量和静态变量初始化为默认值?
为什么不只留下垃圾值呢?有什么特殊原因吗?
Answers:
安全性:单独保留内存会泄漏其他进程或内核的信息。
效率:在将值初始化为某种值之前,这些值是无用的,并且在具有展开循环的块中将它们归零会更有效。当系统空闲时,而不是在某些客户端或用户正在等待程序启动时,操作系统甚至可以将空闲列表页面清零。
可重现性:单独保留这些值将使程序行为不可重复,从而使错误很难发现。
优雅:如果程序可以从0开始,而不必使用默认的初始化程序使代码混乱,则更加简洁。
然后,您可能会想知道为什么auto
存储类确实会作为垃圾启动。答案有两个:
从某种意义上讲不是。每个级别的第一个堆栈帧页面(即,添加到堆栈中的每个新页面)的确接收零值。同一堆栈级别的后续函数实例看到的“垃圾”或“未初始化”值实际上是您自己的程序及其库的其他方法实例留下的先前值。
与初始化任何东西(函数局部变量)有关,可能会有二次(或其他)运行时性能损失auto
。一个函数可能不使用任何大数组中的任何一个或全部,例如,在任何给定的调用中,它可能被调用数千或数百万次。静态和全局变量OTOH的初始化只需发生一次。
main()
调用when时,没有告诉运行时在那之前对堆栈做了什么。更不用说局部变量甚至可能不会出现在堆栈中(例如,它可能仅存在于寄存器中)。就C / C ++本地而言,栈可能被零初始化是无意义的信息。
因为通过操作系统的适当配合,可以在没有运行时开销的情况下实现0初始化静态变量和全局变量。
第6.7.8节C99标准(n1256)的初始化回答了这个问题:
如果具有自动存储期限的对象未明确初始化,则其值不确定。如果未明确初始化具有静态存储持续时间的对象,则:
—如果具有指针类型,则将其初始化为空指针;
—如果具有算术类型,则将其初始化为(正数或无符号)零;
—如果是集合,则根据这些规则(递归)初始化每个成员;
—如果是联合,则根据这些规则(递归)初始化第一个命名成员。
想一想,在静态领域中,您无法始终确保某些内容确实已初始化,或者该main已经启动。还有一个静态init和一个动态init阶段,在动态重要的顺序之后,静态一个优先。
如果您没有对静态进行归零,那么您将无法在此阶段完全确定是否已对AT ALL进行了初始化,总之,C ++世界将飞散,而诸如单例(或任何类型的动态静态)之类的基本事物将飞散。 init)简单地停止工作。
要点的答案很热情,但有点愚蠢。这些都可能适用于非静态分配,但没有做到(很好,有时但不是通常)。
the static one first right after the dynamic one
哇?是静态的first
吗?还是right after the dynamic one
?有什么区别?而且,在对象相互依赖的所有情况下,不管存储时间长短,声明的顺序都很重要,不是吗?
在C中,没有显式初始化程序的静态分配对象被初始化为零(对于算术类型)或空指针(对于指针类型)。C的实现通常使用仅由零值位组成的位模式来表示零值和空指针值(尽管C标准不需要)。因此,bss部分通常包括在文件范围内声明的所有未初始化变量(即,在任何函数外部)以及使用static关键字声明的未初始化局部变量。
资料来源:维基百科
static int x;
总是在x
将其设为垃圾的同时int x;
将x
其初始化为零。