std::fill 是清空栈上内置数组最直接安全的方式,需传入正确元素个数而非字节数;memset 仅适用于POD且零值为全0字节的类型;动态数组优先用 new T[N]() 初始化;vector 应构造时指定初值或用 assign/fill 重置。

用 std::fill 清空内置数组(非指针)
对栈上定义的内置类型数组(如 int arr[10]),std::fill 是最直接、语义清晰的方式。它不依赖构造函数,也不触发额外开销,就是老老实实把每个元素设成 0。
常见错误是传错范围:写成 std::fill(arr, arr + 10, 0) 没问题,但若写成 std::fill(arr, arr + sizeof(arr), 0) 就会越界——sizeof(arr) 返回字节数,不是元素个数。
- 必须用
std::fill(arr, arr + N, 0),其中N是元素个数 - 支持所有可赋值类型,包括
char、double、自定义结构体(只要支持= 0) - 编译器通常能内联优化,性能等价于手写循环
memset 能不能用?什么情况下会翻车
memset 快,但只适用于“按字节清零”安全的类型。对 int、char、unsigned short 没问题;对 float、double、含虚函数的类、有非平凡构造/析构的类型,结果未定义。
典型翻车场景:float f[5]; memset(f, 0, sizeof(f)); 看似清零了,但 IEEE 754 的 +0.0 和 -0.0 都算“零”,而 memset 写的是全 0 字节——这恰好等于 +0.0,所以侥幸成功;但换成 double d[1]; memset(d, 0, sizeof(d)); 同样碰巧成立。可一旦类型变成 std::string s[3],memset 直接破坏内部指针,后续访问必崩。
立即学习“C++免费学习笔记(深入)”;
- 只用于 POD 类型且确定其零值字节表示为全 0(如
int、char) - 永远传
sizeof(array),不是sizeof(*array) - 别图快在复杂类型上硬套,出问题很难定位
动态数组(new int[N])怎么安全清零
用 new int[N]() 带空括号初始化,C++ 标准保证会做值初始化(value-initialization),对 int 就是 0。这是最省心的方式,比 new int[N]{} 更早被广泛支持。
如果已经分配完,再清零,就回到前面两条路:std::fill 或 memset(仅限 POD)。千万别用 delete[] arr; arr = new int[N];——这不初始化,内容是随机值。
-
int* arr = new int[100]();→ 全 0 -
int* arr = new int[100]{};→ 效果相同,C++11 起支持 -
int* arr = new int[100];→ 不初始化,内容未定义
用 std::vector 替代裸数组时的初始化习惯
裸数组清零本质是补救“没初始化”的设计缺陷。std::vector 从构造起就该考虑初始状态:要全 0,就直接构造;要后期重置,就调 assign 或 fill。
容易忽略的是 resize 行为:v.resize(100) 对 int 不保证填 0(取决于实现),而 v.resize(100, 0) 明确指定填充值,才可靠。
- 构造时就定好:
std::vector<int> v(100, 0);</int> - 已有 vector 需重置:
v.assign(100, 0);或v.clear(); v.resize(100, 0); - 避免
v.resize(100);后假设元素为 0 —— 这是未定义行为
真正麻烦的从来不是“怎么清零”,而是“谁负责清零”和“什么时候清零”。栈数组忘了初始化、堆数组漏掉括号、vector 用错 resize 重载……这些地方一漏,bug 往往延迟暴露,调试时得倒查三步。










