sizeof算数组长度仅对栈上未退化的原生数组有效,因传参时数组会退化为指针导致失效;std::size(C++17起)是更安全的统一替代方案,支持原生数组、std::array、std::vector等。

直接用 sizeof 算数组长度只在栈上原生数组有效
很多人一上来就写 sizeof(arr) / sizeof(arr[0]),结果在函数参数里失效——因为数组传参会退化为指针,sizeof 返回的是指针大小(通常是 8),不是原数组字节数。这招只对定义在当前作用域、未退化的栈数组管用:
-
int arr[5] = {1,2,3,4,5};→sizeof(arr)是 20(假设int为 4 字节) -
void foo(int a[]) { sizeof(a); }→ 这里a是int*,sizeof(a)恒为指针大小 - 全局数组、
static数组也适用sizeof,但一旦取地址或作为参数传递,就不可靠
std::size(C++17 起)是更安全的替代方案
std::size 是标准库提供的函数模板,它对原生数组、std::array、std::vector 等容器都返回元素个数,且不依赖 sizeof 推导,因此不会在退化场景下出错:
- 对栈数组:
int arr[7]; std::size(arr)返回7,底层仍是sizeof+ 类型推导,但封装后语义清晰、不易误用 - 对
std::vector:v.size()和std::size(v)效果一致,但后者可统一接口(比如泛型算法中) - 注意:
std::size不支持 C 风格字符串字面量如"hello"的长度(它算的是含\0的总字节数),要长度用std::char_traits或::length strlen
size() 成员函数和 std::size() 的关键区别
别把容器的 .size() 和全局 std::size() 当成一回事——前者是成员函数,后者是 ADL 友好的非成员函数,行为一致但调用方式和适用范围不同:
-
std::vector→ 返回v(10); v.size() size_t,值为10;v.size()是动态的,随插入/擦除变化 -
std::array→ 编译期常量,返回a; a.size() 12;std::size(a)同样返回12,且可用于constexpr上下文 -
std::size对用户自定义容器也有效,只要它提供size()成员或自由函数重载(通过 ADL 查找) - 性能无差异,但
std::size更适合写泛型代码,避免硬写.size()导致对原生数组编译失败
常见错误:混淆 sizeof 和 size() 导致越界或逻辑错
最典型的坑是把 sizeof(ptr) 当成所指内存长度,或者对 new 出的数组用 sizeof:
立即学习“C++免费学习笔记(深入)”;
-
int* p = new int[100]; sizeof(p)→ 返回 8(指针大小),不是 400 -
char buf[256]; sizeof(buf)→ 正确得 256,但若写成sizeof(buf)/sizeof(char)就多余,因为sizeof(char)恒为 1 -
std::string s = "abc"; s.size()返回 3,但sizeof(s)是对象自身内存占用(通常 24 或 32 字节),和内容长度无关 - 用
std::vector::data()获取裸指针后,别幻想还能用sizeof算长度——必须靠.size()或保存原始 size 值
真正需要长度时,优先查类型是否支持 .size() 或 std::size();只有确定是栈上固定数组且未退化,才考虑 sizeof,而且要加 static_assert 保护,比如:static_assert(std::is_array_v









