c++中“数组秩”指编译期确定的数组维度数量,如int[5]秩为1、double3秩为2;由std::rank_v在编译期计算,仅适用于数组类型,指针和非数组类型秩均为0。

什么是C++里的“数组秩”?别被术语吓住
“秩”(Rank)在C++里不是运行时能算出来的值,而是类型系统在编译期就确定的维度数量。比如 int[5] 是一维,秩为1;double[3][4] 是二维,秩为2;char[2][3][4][5] 秩为4。它和线性代数里的矩阵秩(matrix rank)完全无关——后者要算行向量组的极大线性无关组,得跑SVD或高斯消元,而这里只是问“这个数组有几层方括号”。
std::rank 是标准解法,但只能用于编译期
从C++11起,<type_traits></type_traits> 提供了 std::rank 类型特征,它是个模板变量(C++17起)或类模板(C++11/14),返回 size_t 类型的编译期常量:
static_assert(std::rank_v<int> == 1, ""); static_assert(std::rank_v<float> == 3, ""); static_assert(std::rank_v<char> == 1, ""); // 未定长数组也算1维 static_assert(std::rank_v<int> == 0, ""); // 指针秩为0 static_assert(std::rank_v<int> == 0, ""); // 非数组类型秩为0</int></int></char></float></int>
注意:std::rank 对运行时分配的数组(如 new int[10])无效——因为指针本身不是数组类型,std::rank_v<int></int> 永远是0。
想在运行时“推导”数组长度?那得靠模板参数推导
如果你真正想要的是“怎么知道传进来的数组到底有几维”,必须把数组以引用方式传入函数模板,让编译器推导类型:
template <typename t size_t n>
constexpr size_t get_rank() { return std::rank_v<t>; }
<p>template <typename t size_t n>
constexpr size_t get_rank(T (&)[N]) {
return 1 + get_rank<t>(); // 递归拆最外层
}</t></typename></p>
<p>// 用法:
int a[3][4][5];
static_assert(get_rank(a) == 3, "");</p></t></typename>
这种写法依赖数组引用形参,无法处理指针、std::vector 或运行时大小数组。一旦你写成 void f(int* p),信息就彻底丢失了。
常见误判点:sizeof 和 std::extent 不是秩
有人试图用 sizeof(arr)/sizeof(arr[0]) 算第一维长度,但这和秩无关;也有人混淆 std::extent——它取的是某一个维度的大小(如 std::extent_v<int></int> 是3,std::extent_v<int></int> 是4),不是维度数量本身。
最容易踩的坑是:把动态容器当数组用。例如:
-
std::vector<:vector>></:vector>的类型是嵌套容器,std::rank_v返回0 -
std::array<:array>, 4></:array>是类型安全的多维数组,std::rank_v正确返回2 - 用
auto arr = new int[10][20];?不行——这行代码根本不能编译,C++不允许 new 出多维数组(除非用一维模拟)
秩是类型属性,不是数据属性。只要类型不是数组,就不存在“秩”这个概念——这点比大多数人的直觉更严格。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











