std::size 是现代 c++ 获取数组长度的首选方案,它通过模板推导原生数组维度、返回 std::size_t、编译期检查防指针退化,安全简洁;自定义模板需用引用形参并处理 cv 限定。

为什么 std::size 是首选方案
现代 C++(C++17 起)直接提供 std::size,它对原生数组做模板推导并返回 std::size_t 类型的长度,安全、简洁、无需自定义。它内部就是靠模板参数推导数组维度实现的,比如 int arr[5] 传入后能准确得到 5。
常见错误是手动写 sizeof(arr)/sizeof(arr[0]) —— 这在数组退化为指针时彻底失效(比如传进函数后),而 std::size 在编译期检查参数是否为数组,不接受指针,天然防错。
实操建议:
- 优先用
#include <iterator></iterator>后调用std::size(arr) - 不要对形参为
T*或std::vector的变量调用它——会编译失败,这反而是好事,说明你意识到了类型差异 - 它支持多维数组,
std::size(arr)返回第一维大小,std::size(arr[0])得第二维
自己写模板函数推导时,必须用引用形参
如果因兼容旧标准或教学需要手写推导,核心陷阱在于:形参不能是数组类型(C++ 不允许),也不能是指针,必须是「对数组的引用」,否则推导失败或退化为指针。
错误写法:template<typename t size_t n> constexpr size_t array_size(T (&)[N]) { return N; }</typename> 是对的;但若漏掉 & 写成 T [N],实际等价于 T*,N 就无法推导。
实操建议:
- 签名必须是
template<typename t size_t n> constexpr size_t get_size(T (&arr)[N])</typename> - 返回类型推荐
constexpr size_t,确保编译期可用 - 加上
noexcept更严谨:constexpr size_t get_size(T (&arr)[N]) noexcept - 注意:该函数无法接收
const int[5]以外的 cv-qualified 数组,除非模板加const T分支或使用std::remove_cvref_t
std::extent 和 std::rank 适合元编程场景
当你不在运行时要数值,而是在类型层面做编译期判断(比如 SFINAE 或 if constexpr),std::extent_v<t n></t> 和 std::rank_v<t></t> 更合适。它们不操作对象,只读类型信息。
例如 std::extent_v<int></int> 是 3,std::extent_v<int></int> 是 4;std::rank_v<int></int> 是 2。但对 int*,所有 extent_v 都是 0。
实操建议:
- 头文件是
<type_traits></type_traits> - 和
std::is_array_v<t></t>搭配用,避免对非数组类型误用 - 不适用于获取运行时数组长度(比如栈上变长数组 VLAs,C++ 不支持,别试)
- 在
constexpr if中区分int[5]和std::array<int></int>时很实用
容易被忽略的边界情况:字符串字面量和 const 限定
字符串字面量如 "hello" 类型是 const char[6](含末尾 \0),用 std::size 或自定义模板都能正确推导出 6。但若你声明 const char* p = "hello";,再对 p 调用就会失败——因为此时已是指针。
另一个坑是模板未覆盖 const 修饰:若只写了 template<typename t size_t n> size_t f(T (&)[N])</typename>,传入 const int a[3] 会匹配失败,因为 T 被推为 int,而实际类型是 const int。
实操建议:
- 测试时务必覆盖
const int arr[5]、volatile char buf[10]等带 cv 限定的数组 - 更健壮的手写模板应写成
template<typename t size_t n> constexpr auto get_size(T (&)[N]) noexcept -> decltype(N)</typename>,或用std::remove_cv_t<t></t>提取基类型 - VS 和 GCC 对字符串字面量的数组推导行为一致,但 Clang 在某些老版本里对宽字符字面量
L"abc"可能有差异,建议统一用std::size避坑
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











