用 sizeof 计算数组长度仅在定义作用域内有效,因函数参数会退化为指针;推荐优先使用 std::size,或模板 constexpr array_size 获取编译期长度。
用
计算数组长度时,必须确保传入的是原生数组而非指针
很多人写
却得到错误结果,根本原因是:函数参数一旦声明为
或
,数组就退化为指针,
返回的是指针大小(通常是 8),而不是整个数组
字节
数。
正确做法是只在数组定义
作用域
内使用该技巧:
✅ 在定义处直接计算:
❌ 不要在函数内对形参这么干:
⚠️ 字符串字面量要注意结尾
:
是 4,不是 3
用模板推导数组大小,安全且泛型友好
模板可以捕获数组维度信息,绕过退化问题。核心是让编译器从实参类型中推导出长度 N:
基础写法:
调用
就能拿到 N
更实用的封装(C++17 起):
这和
标准库
行为一致
注意不能用于动态分配内存(如
)或
,它们不是数组类型
为什么
和
都值得了解
是 C++17 引入的通用容器大小访问接口,对原生数组、
、
等都有效;而
是编译期常量,专用于查询多维数组某维度大小:
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
立即学习
“
C++免费学习笔记(深入)
”;
→ 运行时可调用,类型安全,推荐日常使用
→ 得到 3;
→ 得到 4;仅适用于已知维度的数组类型,不能用于变量
二者不冲突:前者面向值,后者面向类型;
在元编程中更底层、更早可用
容易被忽略的边界情况:多维数组、引用折叠、const/volatile 修饰
模板推导对 cv 限定符和引用很敏感,稍不注意就会匹配失败:
如果数组是
,模板参数需写成
或更稳妥地用
处理
二维数组传入一维模板会失败:
类型是
,不是
;需显式指定第二维或用嵌套模板
引用折叠可能导致意外:比如
形参 + 数组左值,会触发引用折叠为
,但原始模板仍需匹配
才能捕获尺寸
最省心的做法:优先用
;若需编译期常量且确定是原生数组,再上模板 +
sizeofsizeof(arr) / sizeof(arr[0])T arr[]T* arrsizeofint arr[] = {1, 2, 3, 4};
size_t n = sizeof(arr) / sizeof(arr[0]); // 得到 4void foo(int arr[]) {
size_t n = sizeof(arr) / sizeof(arr[0]); // 错!arr 是 int*,结果恒为 1(64 位下)
}\0sizeof("abc")template
constexpr size_t array_size(T (&)[N]) {
return N;
}array_size(arr)template
constexpr size_t size(const T (&)[N]) noexcept {
return N;
}std::sizenew int[5]std::vectorstd::sizestd::extent_vstd::sizestd::arraystd::vectorstd::extent_vstd::size(arr)std::extent_vstd::extent_vstd::extent_vconst int arr[5]const T (&)[N]std::remove_cv_tint mat[2][3]int[2][3]int[]T&&T&T(&)[N]std::sizeconstexpr