为什么在C ++中打印一个未初始化的variables?
为什么打印32767
(或其他一些随机数)? 什么是std::cout
打印? 为什么它不是NULL
(或0
)?
int main() { int a; std::cout << a; }
这是因为具有自动存储持续时间的variables在C ++中不会自动初始化为零。 在C ++中,你不需要支付你不需要的东西,而且自动初始化一个variables需要花费时间(设置为零,一个内存位置最终会减less到机器指令,然后转换成电信号来控制物理位)。
该variables正在保留一个内存位置,并发生了一些垃圾在该内存位置。 那个垃圾正在被cout
打印出来。
正如@dwcanillas指出的那样,这是不确定的行为。 相关: 在C中声明,未初始化的variables会发生什么? 它有价值吗?
从C ++标准(强调我的):
8.5初始化程序[dcl.init]
7) 默认初始化typesT的对象意味着 :
- 如果T是(可能是cv-qualified)类types(第9章),则考虑构造函数。 枚举适用的构造函数(13.3.1.3),通过重载决策(13.3)select最好的构造函数()。 被选中的构造函数被调用,用一个空的参数列表来初始化>>对象。
- 如果T是一个数组types,每个元素都是默认初始化的。
- 否则,不执行初始化。
12) 如果没有为对象指定初始化程序,则该对象将被默认初始化 。 当获得具有自动或dynamic存储持续时间的对象的存储时,该对象具有不确定的值,并且如果没有对该对象执行初始化,那么该对象将保留不确定的值直到该值被replace(5.18)。 [注意:具有静态或线程存储时间的对象是零初始化的,见3.6.2。 – 结束注释] 如果评估产生了不确定的值,除非在下列情况下,行为是不确定的 :
– 如果通过评估产生了无符号的窄字符types(3.9.1)的不确定值:
– 条件expression式(5.16)的第二个或第三个操作数,
– 逗号expression式(5.19)的右操作数,
– 强制转换的操作数或转换为无符号的窄字符types(4.7,5.2.3,5.2.9,5.4)或
– 丢弃值expression式(第5章)
…
这是未定义的行为。 你正在打印任何占用内存的东西,在这种情况下恰好是32767
。
行为被C ++ 14(N3936)[dcl.init] / 12覆盖:
如果没有为对象指定初始化程序,则该对象将被默认初始化。 当获得具有自动或dynamic存储持续时间的对象的存储时,对象具有不确定的值 ,并且如果没有对该对象执行初始化,则该对象将保留不确定的值,直到该值被replace。
[…]如果评估产生了不确定的值,除非在以下情况下, 行为是不确定的 :
而且你的代码没有被任何“下面的情况”所覆盖,这些情况涵盖了允许unsigned char
不确定值传播的几种情况。
因为“a”不是全局/静态的。 它是一个在运行时进行初始化的自动variables。 如果是全局的,则在编译时初始化为零。 即
•静态variables在编译时被初始化,因为它们的地址是已知的并且是固定的。 将它们初始化为0不会产生运行时成本。
•对于不同的调用,自动variables可以具有不同的地址,每次调用函数时都必须在运行时进行初始化,从而产生可能不需要的运行时成本。 如果你确实需要这个初始化,然后请求它。