C++中void func(int arr[])实际传指针而非引用,因数组参数自动退化为int*;正确做法是用模板推导长度并声明引用类型int (&arr)[N],或C++20的std::span实现类型安全与长度检查。

为什么不能直接用 void func(int arr[]) 传数组引用
这种写法实际上传的是指针,不是引用。C++ 中 int arr[] 在函数参数里会自动退化为 int*,丢失长度信息,也无法阻止数组被隐式转换——你根本没法在函数内用 sizeof(arr) 得到真实大小,decltype(arr) 也是指针类型。
- 即使你声明
void func(int arr[5]),编译器照样当int*处理 - 无法绑定到临时数组,也不能防止调用时传入长度不符的数组
- 想靠它实现“只接受 5 元素数组”的约束?做不到
正确写法:用模板推导数组长度 + 引用声明
必须显式写出数组长度和引用符号 &,且长度得是编译期常量。最稳妥的方式是用模板让编译器自己推:
template <size_t N>
void process_array(int (&arr)[N]) {
// 这里 arr 是真正的 int[5]& 类型
std::cout << "size: " << N << "\n"; // N = 5
}- 调用时
int a[5] = {1,2,3,4,5}; process_array(a);才能成功匹配 - 如果传
int b[3],会实例化出另一个process_array<3>版本 - 传
std::vector<int>或new int[5]直接编译失败——这正是你想要的安全性
如果必须支持不同长度,用 std::span(C++20)
模板方案虽然安全,但每次长度不同就生成新函数,代码膨胀。C++20 的 std::span 提供运行期长度 + 编译期类型安全:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
#include <span>
void handle_span(std::span<const int> s) {
for (int x : s) { /* ... */ }
std::cout << s.size(); // 安全获取长度
}- 可接受
int arr[10]、std::vector<int>、std::array<int,7> - 底层仍是轻量级指针+长度,无拷贝开销
- 注意:MSVC 19.29+、GCC 10+、Clang 9+ 才完整支持;老编译器可用
gsl::span替代
常见错误:把 int& arr[] 当成“数组引用”
这个语法合法,但含义是“元素为 int& 的数组”,即 int&[5],不是“对整个数组的引用”。它要求你传入 5 个独立的 int&,比如:
立即学习“C++免费学习笔记(深入)”;
int a=1,b=2,c=3,d=4,e=5;
func({a,b,c,d,e}); // OK —— 传 5 个引用- 你无法用一个数组变量(如
int x[5])直接初始化它 - 几乎没人这么用,容易和
int (&arr)[5]混淆,建议彻底避开 - 真要引用多个变量,用
std::tie或结构体更清晰
数组引用的核心就两点:长度必须已知,引用符号 & 必须紧贴括号。漏掉任一,就不是你想要的“整个数组按引用传递”。

















