跳转到主内容
极星编程网:以代码为星,赴技术山海!

C++ 怎么获取数组长度 C++ sizeof与template推导数组大小【技巧】

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

相关文章