c++中数组引用必须指定编译期常量长度,如int (&arr)[5],不可省略维度或写为int& arr;它绑定栈上具名数组,零开销且类型安全,但不支持动态长度。

函数参数声明为数组引用时必须指定长度
直接写 int& arr 是错的,这声明的是单个 int 的引用,不是数组。C++ 中数组引用必须带维度,比如 int (&arr)[5] 表示“对长度为 5 的 int 数组的引用”。编译器靠这个长度信息做类型检查和内存布局计算,漏掉会编译失败或误用指针。
常见错误现象:error: declaration of 'arr' as array of references 或意外退化成指针导致修改无效。
- 声明语法固定:
void func(int (&arr)[N]),N必须是编译期常量(如字面量、constexpr变量) - 不能写
int (&arr)[]—— C++ 不支持不完整类型的数组引用 - 若想泛化长度,得用模板:
template<size_t n> void func(int (&arr)[N])</size_t>
传入实参时不能发生数组到指针的隐式转换
数组引用参数拒绝接受临时数组或指针,这是它的安全机制,但也是新手最容易卡住的地方。例如,你写了 func(arr),但 arr 是一个 int* 或函数返回的局部数组(已退化),就会编译失败。
使用场景:只适用于栈上定义的、生命周期足够长的具名数组。
- ✅ 正确:
int data[3] = {1,2,3}; func(data); - ❌ 错误:
func(new int[3]);(类型不匹配,且new返回指针) - ❌ 错误:
func(std::vector<int>{1,2,3}.data());</int>(得到的是int*,不是数组引用) - ⚠️ 注意:
extern int global_arr[4];这种全局数组可以传,但必须确保声明长度与函数签名一致
修改数组内容确实会反映到原数组,但无法改变数组长度
数组引用本身不拥有数据,只是别名,所以对 arr[i] 的赋值直接作用于原内存。但它不能 resize、不能指向别的数组,也不能用于动态大小场景。
性能影响:零开销 —— 没有拷贝,没有指针间接寻址(相比 int* 参数,引用在优化后通常等价于直接访问原地址)。
- 可以安全写
arr[0] = 42;、for (auto& x : arr) x *= 2; - 不能写
arr = another_arr;(数组不可赋值) - 不能通过它调用
sizeof(arr)来获取运行时长度 —— 结果永远是sizeof(int) * N,跟声明时的N绑定
替代方案对比:什么时候该用指针或 std::span
如果你需要处理不同长度的数组、堆内存、或来自容器的数据,硬用数组引用反而增加限制。现代 C++ 更推荐 std::span(C++20)或带长度的指针+size 参数。
-
void func(int* arr, size_t n):兼容一切,但丢失类型安全,需手动传长度 -
void func(std::span<int> s)</int>:保留范围语义,支持vector、数组、指针+长度构造,且可读写 -
template<typename t size_t n> void func(std::array<t>& arr)</t></typename>:比原始数组引用更安全,提供成员函数
数组引用最适用的场景其实很窄:明确知道长度、确定是栈数组、且想用编译期检查堵住误传指针的漏洞。一不留神就撞墙,别为了“引用”二字硬套。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











