std::size最安全(C++17起),仅适用于静态数组,对函数参数中的数组会编译失败以提前暴露问题;sizeof/sizeof[0]易出错,模板array_size可兼容老标准并杜绝指针误用。

用 std::size 最安全(C++17 起)
只要数组是真正的静态数组(不是指针或动态分配),std::size 是首选:它类型安全、可读性强,且对多维数组也适用。
常见错误是把它用在函数参数里的数组——那其实退化成了指针,std::size 会编译失败,这反而是好事,能提前暴露问题。
int arr[5] = {1,2,3,4,5}; auto n = std::size(arr); // n 是 size_t,值为 5- 对
const int arr[3]同样有效 - 不适用于
int* p = new int[5]; std::size(p)—— 编译报错:no matching function for call to 'size'
sizeof(arr) / sizeof(arr[0]) 仍可用,但要小心边界
这是 C 风格的写法,在 C++ 中依然合法,但容易出错:一旦 arr 是指针或引用,结果就完全不可靠。
尤其要注意 arr[0] 的类型必须和整个数组元素类型一致;如果数组是 char[10],而你误写成 sizeof(arr) / sizeof(int),结果就是错的。
立即学习“C++免费学习笔记(深入)”;
- 正确:
int arr[7]; size_t n = sizeof(arr) / sizeof(arr[0]); - 危险:
void func(int a[]) { return sizeof(a) / sizeof(a[0]); }→ 总是返回 1(因为a是int*,sizeof(int*) / sizeof(int)在多数平台是 8/4=2 或 4/4=1) - 更危险:
char buf[256]; size_t len = sizeof(buf) / sizeof(short);→ 得到 128,但语义完全错误
模板推导 + constexpr 封装(兼容老标准)
如果你还在用 C++11/14,或者想彻底杜绝传入指针的可能,可以自己写一个 constexpr 模板辅助函数:
template<typename T, size_t N>
constexpr size_t array_size(const T (&)[N]) { return N; }它利用了数组引用的类型信息,编译期就能算出长度,且对指针输入直接不匹配,不会静默出错。
int x[12]; auto n = array_size(x); // n == 12,constexprint* p; array_size(p); // 编译错误:no matching function- 注意不能用于
std::array或容器——它只认原生数组
别把 std::vector 和静态数组搞混
看到“静态数组”就下意识写 .size() 是常见误区。只有 std::vector、std::array 这类对象才有成员函数 size();原生数组没有成员函数,调用 arr.size() 会编译失败。
int arr[10]; arr.size(); // 错误:‘int [10]’ has no member named ‘size’std::array<int, 10> a; a.size(); // 正确std::vector<int> v(10); v.size(); // 正确,但 v 是动态的,不是静态数组
真正容易被忽略的是:函数形参里声明的 int a[N] 不是数组类型,只是语法糖,实际是 int* a。所有“求数组长度”的技巧,在函数内部对形参都失效——这点必须手写注释或用模板约束来守住。


















