c++中数组名传参实际传指针,void func(int arr[5])的[5]被忽略,arr本质是int*,sizeof(arr)返回指针大小(如8),无法获知原数组长度,易致越界访问。

为什么不能直接传数组名
在 C++ 中,void func(int arr[5]) 这种写法看起来像在传数组,实际上传的是指针——编译器会悄悄把 arr 当作 int* 处理,长度信息 [5] 完全被忽略。调用时即使传入长度为 3 的数组也不会报错,但 sizeof(arr) 在函数内永远是 8(64 位下指针大小),不是数组真实字节数。
常见错误现象:std::cout 在函数内输出 1,而非预期的元素个数;越界访问不触发编译警告,运行时可能崩溃。
- 数组名作为参数时自动退化为指针,这是 C 兼容行为,无法绕过
- 模板推导可保留大小,但仅限于“实参是具名数组”且未退化的情形(如直接传
my_array,而非&my_array[0]) - 如果函数需要知道长度,必须额外传一个
size_t len参数,或改用容器
用 std::array 传固定大小数组
std::array 是栈上分配、大小固定的容器,能完整传递类型和长度信息,支持拷贝、赋值和 size() 方法,且无堆分配开销。
实操建议:
- 声明函数时写明具体大小:
void process(const std::array<int>& arr)</int>—— 编译器据此做类型检查 - 调用时直接传数组变量:
std::array<int> data = {1,2,3,4,5}; process(data);</int> - 不要用
std::array<int n></int>模板参数试图泛化大小(N不是类型参数,不能自动推导);需配合模板函数 - 若需支持不同长度,定义模板函数:
template<size_t n> void process(const std::array<int n>& arr)</int></size_t>
用 std::vector 传动态大小数组
当数组长度在运行时确定,或需要增删元素时,std::vector 是更自然的选择。它把数据和长度封装在一起,避免手动管理 size 参数。
关键点:
- 优先按 const 引用传递:
void process(const std::vector<int>& vec)</int>,避免不必要的拷贝 - 不要传
std::vector<int>*</int>或裸指针——失去边界检查,且无法调用vec.size()等成员函数 -
std::vector的data()可返回T*,用于对接 C 风格 API,但需确保 vector 不被 resize 或析构 - 性能影响:小数组(如 ≤ 16 个 int)用
std::array更快;频繁变长或不确定大小时,std::vector更安全
用模板 + 引用捕获数组大小
如果坚持用原始数组语法(比如要兼容旧代码或嵌入式环境),可以用模板参数推导数组长度:
template<typename t size_t n>
void process(T (&arr)[N]) {
// arr 是引用,不会退化;N 是编译期常量
for (size_t i = 0; i <p>这个写法的关键限制:</p>
<ul>
<li>只能接受具名数组变量(如 <code>int a[3]; process(a);</code>),不能接受指针、new 出来的数组、或函数返回的数组</li>
<li>无法接受 <code>std::vector</code> 或 <code>std::array</code> —— 类型不匹配</li>
<li>若数组是全局或 static 的,仍可用;但作为函数局部变量时,生命周期必须覆盖调用过程</li>
<li>多维数组需写成 <code>T (&arr)[Rows][Cols]</code>,不能只写第一维</li>
</ul>
<p>真正容易被忽略的是:一旦数组被隐式转换为指针(比如先赋给 <code>int* p = arr;</code> 再传 <code>p</code>),模板就失效了——它只对“原生数组名”起作用。</p></typename>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











