不能直接传 int arr[n],因为数组会退化为指针,丢失尺寸信息且无引用语义;正确方式是模板推导n并用int (&arr)[n]声明数组引用,既保尺寸又避拷贝。

为什么不能直接传 int arr[N]?
因为形参写成 int arr[N] 本质是数组退化为指针,N 完全被忽略,编译器只看到 int*。你失去所有尺寸信息,也得不到引用语义——这和“传递固定大小数组引用”的目标背道而驰。
正确写法:用模板推导 N + 数组引用语法
核心是把数组长度作为模板非类型参数捕获,并声明为引用。这样既保尺寸、又避拷贝:
template <size_t n>
void process(const int (&arr)[N]) {
// arr 是对 int[N] 的引用,N 在编译期已知
static_assert(N == 5, "only accept arrays of size 5"); // 可静态校验
}</size_t>
调用时直接传栈上数组即可:int data[5] = {1,2,3,4,5}; process(data);。注意:不能传 new int[5] 或 std::vector,它们不是 C 风格数组。
常见错误:误用指针或 std::array 混淆场景
有人会写 void f(int* arr, size_t n) —— 这根本不是引用,也不限定大小;也有人想用 std::array<int n>&</int>,它确实安全,但前提是调用方也用 std::array,无法兼容原始数组字面量或 C API。
-
process({1,2,3})会失败:列表初始化不能绑定到非 const 引用(需加const&) - 若函数需修改数组,去掉
const,但调用方必须确保数组非常量(如非字面量、非临时对象) - 模板实例化后,每个
N生成独立函数,无运行时开销,但可能增加代码体积
替代方案:C++17 起可用 std::span 简化接口
如果只需读/写一段连续内存且接受多种来源(std::array、std::vector、原始数组),std::span 更灵活:
void process(std::span<const int> s) {
if (s.size() != 5) throw std::invalid_argument("expected size 5");
}</const>
它不提供编译期尺寸保证,但统一了接口。真正需要“编译期强制 N”时,模板数组引用仍是不可替代的。
最易被忽略的是:数组引用语法中的括号不能省——int& arr[N] 是 N 个 int& 的数组,int (&arr)[N] 才是对整个数组的引用。少一对括号,语义天差地别。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











