C++ 怎么获取数组长度 C++ 模板函数推导数组大小技巧【泛型】

9次阅读

std::size最安全,c++17起支持上数组和容器,底层为sizeof(arr)/sizeof(arr[0])封装;函数参数中数组会退化为指针致其失效,需模板引用int(&)[N]推导长度。

C++ 怎么获取数组长度 C++ 模板函数推导数组大小技巧【泛型】

std::size 最安全,C++17 起直接支持

对普通数组(非指针),std::size 是首选。它底层调用 sizeof(arr)/sizeof(arr[0]),但做了类型安全封装,且对容器也通用。

  • 只适用于上定义的数组,比如 int arr[5];,不适用于 int* arr = new int[5];
  • 在函数参数中传入数组时会退化为指针,std::size 失效 —— 这是新手最常踩的坑
  • 示例:
    int a[] = {1, 2, 3}; static_assert(std::size(a) == 3); // ✅ 编译期确定

模板参数推导数组长度:靠引用 + sizeof 手动算

当必须把数组作为函数参数传入并获取长度时,只能靠模板 + 引用限定符阻止退化。

  • 函数签名必须写成 template void foo(int (&arr)[N])(&arr)[N] 表示“对 N 元素数组的引用”
  • N 会在编译期被自动推导,可用于返回、计算或 static_assert
  • 错误写法:void foo(int arr[])void foo(int* arr) → 完全丢失长度信息
  • 示例:
    template size_t get_len(int (&)[N]) { return N; } 

    int x[42]; auto n = get_len(x); // n == 42,类型安全,无运行时开销

为什么不能用 sizeof 在函数内部直接算?

因为数组一进函数就变指针,sizeof 返回的是指针大小(通常是 4 或 8),不是原数组大小。

  • 现象:void bad(int a[]) { std::cout → 输出 8(x64 下),不是原数组字节数
  • 根本原因:C++ 标准规定,形参中的数组声明等价于指针声明,语法糖而已
  • decltype(a) 都是 int*,没有任何元信息残留

泛型场景下更推荐 std::arraystd::span

如果控制不了调用方是否传原始数组,或需要真正泛型(兼容 std::vector、原始数组、C 风格字符串),优先用标准库容器视图。

立即学习C++免费学习笔记(深入)”;

  • std::array 自带 .size(),且是聚合类型,可模板推导;但它要求编译期确定大小
  • std::span(C++20)能统一处理原始数组、std::vectorstd::array,构造时自动捕获长度:std::span s{arr};s.size() 可用
  • 注意:std::span 不拥有数据,仅是视图,别让它悬空

原始数组长度推导本质是编译期契约:你得让类型系统“看见”维度。一旦退化成指针,所有信息就不可逆地丢了。

text=ZqhQzanResources