局部数组未初始化时元素值随机;全局/静态数组因bss段清零而为0;动态分配需()才初始化为0;{0}仅初始化首元素,其余靠默认值填充。

局部数组不初始化时,每个元素的值是随机的、不可预测的;全局或静态数组未显式初始化时,默认值才是 0。
全局/静态数组默认值为 0 是编译器行为,不是语言“保证”
全局变量(包括全局数组)和 static 数组会被放进 BSS 段,该段在程序加载时由操作系统清零。所以它们看起来“默认为 0”,但本质是链接和加载阶段的约定,不是 C++ 语义上的“初始化”。
-
int global_arr[10];→ 所有元素为 0 -
static int local_static[5] = {42};→local_static[0]是 42,local_static[1..4]是 0(因为初始化列表不足,补默认值) - 这种清零不适用于堆上分配的内存(比如
new int[10]),除非加()
int arr[N] = {0} 只让第一个元素为 0,其余靠“补默认值”才全为 0
这是最常被误解的点:{0} 并不是“把整个数组设为 0”,而是提供一个含单个元素的初始化列表。C++ 规则规定:当初始化列表长度小于数组长度时,剩余元素用对应类型的默认值填充(int() 即 0)。
-
int a[5] = {1};→a[0]==1,a[1..4]==0 -
int b[5] = {};→ 等价于int b[5] = {0};,全部为 0(C++11 起支持) -
int c[5] = {0, 0, 0, 0, 0};→ 显式全写,没歧义,但冗余
局部数组不初始化就是脏数据,别赌运气
函数内定义的 int arr[100]; 不做任何初始化,其内容完全取决于栈上那块内存之前被谁用过。哪怕你本地测试每次都是 0,换编译器、换优化等级、换运行环境就可能崩。
- Clang/GCC 在 debug 模式下有时会填特定值(如
0xCC)帮检测未初始化使用,但 release 下不会 - 用
valgrind或 ASan 运行会直接报use of uninitialized value - 正确做法只有三种:
int arr[100]{};、int arr[100] = {};或memset(arr, 0, sizeof(arr));
动态分配数组的初始化规则更严格
new 出来的数组不加括号,就不会初始化;加了空括号,才触发值初始化(value-initialization),对内置类型即为 0。
-
int* p = new int[10];→ 全部未定义值 -
int* p = new int[10]();→ 全部为 0(注意是(),不是{}) -
int* p = new int[10]{1,2};→ 前两个为 1 和 2,后面八个为 0(C++11 起支持)
真正容易被忽略的是:类类型数组和内置类型数组的初始化逻辑完全不同——前者必须调用构造函数,后者只看有没有触发值初始化。混用时尤其要注意默认构造函数是否存在,否则连编译都过不去。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











