C++中用{}初始化数组时未显式赋值的元素会零初始化。如int a[5]={1},a[1]至a[4]均为0;struct S{int x[3];}s={{1}}中x为{1,0,0};std::array同理;全局数组默认零初始化。

数组初始化列表元素少于声明长度时,C++ 默认用 0 初始化剩余元素
只要使用 {} 初始化(包括 = {}、{...} 等形式),且显式提供了部分初始值,C++ 标准规定:未显式初始化的元素会进行**零初始化**(zero-initialization)。这不是编译器扩展,是 C++11 起的明确行为。
常见错误现象:int a[5] = {1}; 后,a[1] 到 a[4] 都是 0,不是未定义值——这点常被误认为“没初始化”而引发误判。
-
int arr[4] = {1, 2};→arr = {1, 2, 0, 0} -
double b[3] = {3.14};→b = {3.14, 0.0, 0.0} -
char c[6] = {'h', 'i'};→c = {'h', 'i', '\0', '\0', '\0', '\0'}(注意:末尾自动补\0不代表是字符串,只是字节为 0)
聚合类型(如 struct)嵌套数组时,补齐规则同样适用
当结构体是聚合类型(无用户定义构造函数、无私有/保护非静态成员等),其数组成员在初始化时也遵循相同规则。但要注意:如果只提供一个初始值,它会用于第一个成员,而非整个数组。
例如:
立即学习“C++免费学习笔记(深入)”;
struct S {
int x[3];
};
S s1 = {{1}}; // ✅ 正确:外层 {} 包住内层 {},x = {1, 0, 0}
S s2 = {1}; // ❌ 错误理解:这等价于 s2.x[0] = 1,s2.x[1] 和 s2.x[2] 仍为 0 —— 但写法易误导,建议避免
- 推荐显式写成
{{1}},避免歧义 - 若用
= {}形式(如S s = {};),整个x数组全为 0 - 类类型数组(如
std::string str[2] = {"a"};)中未指定元素会调用默认构造函数,不是零初始化
用 std::array 替代原生数组时,补齐行为一致但语法更严格
std::array 是聚合类型,初始化规则与原生数组完全一致,但因模板参数固定,编译期检查更严——比如漏写大括号嵌套会直接报错。
示例:
std::array<int, 4> a1 = {1, 2}; // ✅ a1 = {1,2,0,0}
std::array<int, 4> a2 = {{1, 2}}; // ✅ 等效写法(C++11 允许双大括号)
std::array<int, 4> a3 = {1, 2, 3, 4, 5}; // ❌ 编译失败:初始值过多
- 不能省略外层
{}:写成std::array<int> a = 1;</int>是错的 - 使用
std::array::fill()或循环赋值不属于“初始化列表补齐”,那是运行时操作 - 和原生数组一样,
std::array<t> x{};</t>会零初始化全部元素
别依赖“未初始化”来获得随机值——那其实是未定义行为
有人想用“不填满初始化列表”来获取栈上的“垃圾值”,这是危险的。现代编译器在优化开启时(如 -O2)可能将未显式初始化的局部原生数组直接优化掉,或填充为 0,导致行为不可预测。
- 需要真随机值?用
std::random_device+std::uniform_int_distribution - 需要未定义行为测试?应改用动态分配 +
malloc,并明确不memset - 调试时看到“看似随机”的值,很可能是旧栈帧残留,不代表语言保证
最易被忽略的一点:全局/静态存储期的数组即使不写初始化列表,也会被零初始化——所以“补齐”在这些场景下根本不会暴露问题,反而掩盖了本该主动初始化的意图。


















