sizeof(arr)/sizeof(arr[0])仅对栈/全局原生数组有效;传参退化为指针、new分配、STL容器中均失效,应改用std::array::size()或显式传长度。

sizeof(arr) / sizeof(arr[0]) 为什么有时失效
这个写法只在数组是「栈上定义的原生数组」时才安全。一旦数组退化为指针(比如传入函数、动态分配、或作为类成员),sizeof(arr) 就变成指针大小(通常是 8),结果完全错误。
常见踩坑场景:
- 把数组传给函数后在函数内用
sizeof—— 此时形参已是T*,不是数组类型 -
int* arr = new int[10];,sizeof(arr)返回 8,不是 40 - 用
std::vector或std::array却误套用该公式
std::array 的 size() 是最稳的选择
如果你能控制数组定义方式,优先用 std::array。它的长度是编译期常量,size() 成员函数零开销、类型安全、不会退化。
示例:
立即学习“C++免费学习笔记(深入)”;
std::array<int, 5> arr = {1,2,3,4,5};
std::cout << arr.size(); // 输出 5,类型是 std::size_t
注意:std::array 长度必须是编译期已知常量,不能是变量;它不支持运行时扩容,但正好匹配“固定长度数组”的语义。
函数内怎么安全拿到数组长度
原生数组传参后无法自证长度,必须显式传递。C++ 没有内置的“带长度的数组类型”传参机制。
可行做法:
- 额外加一个参数:
void func(int arr[], std::size_t len) - 用模板推导(推荐):
template<std::size_t N> void func(int (&arr)[N]) { /* N 就是长度 */ } - 改用
std::span<const int>(C++20),它携带数据+长度信息,且可接受原生数组、std::vector、std::array等
模板推导方式在调用时自动捕获长度,但只适用于实参确实是栈数组的情况;std::span 更通用,但需确认编译器支持 C++20。
new[] 分配的数组长度只能靠自己记
动态分配的数组没有元信息存储长度。你用 new int[10],系统不会帮你存下 10 —— 这个数字必须由程序员显式保存。
正确姿势:
- 用
std::vector替代:它内部管理长度,v.size()安全可靠 - 如果非用裸指针,必须配套存一个长度变量:
int* arr = new int[n];,然后始终和n一起传递、一起释放 - 绝不要试图通过地址运算反推长度(比如
end - begin),因为 new 分配的内存块头部没有标准长度字段
真正麻烦的从来不是“怎么算长度”,而是“谁负责维护这个长度”——一旦脱离栈数组上下文,长度就不再是语言特性,而是你的契约责任。


















