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