为什么全局变量和静态变量初始化为默认值?

Xin*_*nus 61 c c++ static global-variables

在C/C++中,为什么全局变量和静态变量初始化为默认值?

为什么不留下垃圾值呢?这有什么特别的原因吗?

Dig*_*oss 68

  1. 安全性:单独留下内存会泄漏来自其他进程或内核的信息.

  2. 效率:在初始化为某些内容之前,这些值是无用的,并且在具有展开循环的块中将它们归零会更有效.当系统处于空闲状态时,操作系统甚至可以将零空闲页面置零,而不是在某个客户端或用户等待程序启动时.

  3. 再现性:单独保留值会使程序行为不可重复,使得很难找到错误.

  4. 优雅:如果程序可以从0开始而不必使用默认初始化程序混乱代码,那就更清晰了.

然后人们可能想知道为什么auto存储类确实以垃圾为起点.答案是双重的:

  1. 某种意义上说,它没有.每个级别的第一个堆栈帧页面(即,添加到堆栈的每个新页面)确实接收零值.同一堆栈级别的后续函数实例看到的"垃圾"或"未初始化"值实际上是您自己的程序及其库的其他方法实例留下的先前值.

  2. 可能存在与初始化(函数本地)到任何事物相关的二次(或任何)运行时性能损失auto.例如,在任何给定的调用中,函数可能不会使用任何或所有大型数组,并且可以调用数千或数百万次.静态和全局变量OTOH的初始化只需要发生一次.

  • 实际上,真正的原因是最初的C标准是编纂现有的做法而不是引入新的东西.并且ANSI-ISO C之前为了提高效率而做到了. (3认同)
  • DigitalRoss:"第一个堆栈帧"通常不会被您编写的代码使用,而是由标准库的程序序言和初始化例程使用.并不是每个操作系统都会在程序启动之前将堆栈(或堆!)内存归零 - 例如MS-DOS(没有?)没有. (3认同)
  • 我想提问者想要知道为什么`static int x;`总是将`x`初始化为零,而`int x;`让`x`为垃圾. (2认同)
  • @DigitalRoss:即使您使用的平台为堆栈提供零填充页面(这是很常见的,但不一定是通用的),这并不意味着第一次调用该函数将导致本地人结束在零填充的内存中。例如,当调用main()时,在此之前并没有告诉运行时对栈做了什么。更不用说局部变量甚至可能不会最终出现在堆栈中(例如,它可能仅存在于寄存器中)。就C / C ++本地而言,栈可能被零初始化是毫无意义的信息。 (2认同)
  • 不。对不起: 1.:错了。堆/堆栈未初始化并且不会泄漏任何内容。2.: 错误与错误:BSS init 需要时间,而 vals 并非无用。3.+4.:同意。第二个列表: 1.:错误。堆栈根本不保证从零开始。2. 同意,但不是问题的答案。这正是_不_在 C/C++ 中初始化内存的原因:运行时开销比 C/C++ 中的安全/安全/优雅具有更高的优先级。对于全局变量,这种运行时开销可以忽略不计。_This_ 是这个问题的答案:它带来的成本非常低,收益却很大,因此以这种方式指定。 (2认同)

R S*_*hko 24

因为通过OS的适当协作,可以实现0初始化静态和全局变量而无需运行时开销.

  • 存在运行时开销(操作系统必须用零填充页面),但出于安全原因无论如何都是需要的。 (2认同)

Jin*_*Yao 17

第6.7.8节C99标准的初始化(n1256)回答了这个问题:

如果未显式初始化具有自动存储持续时间的对象,则其值不确定.如果未显式初始化具有静态存储持续时间的对象,则:

- 如果它有指针类型,则将其初始化为空指针;

- 如果它有算术类型,则初始化为(正或无符号)零;

- 如果是聚合,则根据这些规则初始化(递归)每个成员;

- 如果它是一个联合,则根据这些规则初始化(递归)第一个命名成员.

  • 不回答OP的问题.他知道这一切.他问*为什么.*-1 (5认同)
  • 是的,如果问题中的"C/C++"意味着C/C++标准,我的回答是无关紧要的.否则,它是相关的. (3认同)

Cha*_*ese 6

想一想,在静态领域,你无法确定某些东西确实被初始化,或者主要已经开始了.还有一个静态初始化和一个动态初始化阶段,静态初始阶段就在顺序重要的动态阶段之后.

如果你没有从静态中归零那么你就完全无法在这个阶段告诉你是否有任何事情在全部被初始化,简而言之,C++世界将会分开并且基本的东西如单身(或任何类型的动态静态) init)简单地停止工作.

有关要点的答案很热情,但有点傻.这些都可以适用于非静态分配,但是没有做到(好的,有时但不常见).