int arr[]在函数参数中等价于int*,因数组名会退化为指针并丢失长度;推荐用std::vector替代,或模板推导栈数组长度,堆数组必须显式传长度。

为什么 int arr[] 在函数参数里等价于 int*
这是 C++(继承自 C)的语法设计:数组名作为函数参数时,编译器自动将其“退化”为指向首元素的指针,丢失长度信息。哪怕你写 void foo(int arr[10]),sizeof(arr) 仍是指针大小(通常是 8),不是 40。
用 std::vector 替代裸数组是最直接的解法
std::vector 自带大小、支持拷贝/移动、可变长,且传递时不会退化:
void process(const std::vector<int>& v) {
std::cout << "size: " << v.size() << "\n"; // 安全获取长度
for (int x : v) { /* ... */ }
}- 传参用
const std::vector<T>&避免拷贝开销 - 若需修改原数组,去掉
const;若需所有权转移,用std::vector<T>&& - 调用方无需改逻辑:
process({1,2,3});或process(my_vec);
必须用裸数组?用模板推导长度
如果接口受限(比如对接 C API 或性能敏感场景),可用模板让编译器在编译期捕获数组长度:
template <size_t N>
void process(int (&arr)[N]) {
std::cout << "length: " << N << "\n"; // N 是编译期常量
for (size_t i = 0; i < N; ++i) { /* ... */ }
}- 只能接受真正的栈数组(如
int a[5]; process(a);),不能接受new int[5]或指针 - 无法用于动态分配的堆数组——因为堆数组长度在运行时才确定,模板无法推导
- 函数重载时注意:该签名和
void process(int*)是不同函数,不会冲突
传堆分配数组时,必须显式传长度
对 int* p = new int[n] 这类情况,C++ 没有银弹。你必须手动把长度一起传过去:
立即学习“C++免费学习笔记(深入)”;
void process(int* arr, size_t len) {
for (size_t i = 0; i < len; ++i) { /* ... */ }
}
// 调用:
int* p = new int[100];
process(p, 100);
delete[] p;- 别依赖
nullptr结尾——这不是字符串,没有约定终止符 - 避免只传指针再用
strlen-style 逻辑探测长度,会越界 - 如果用智能指针管理内存,建议搭配
std::unique_ptr<int[]>和额外的size_t参数
最易被忽略的是:模板方案看似完美,但一旦数组来自 malloc、new[] 或函数返回值(如 std::vector::data()),它就完全失效——此时你面对的已经是裸指针,编译器再也看不到原始维度。这时候硬要绕开长度参数,只会埋下越界访问的隐患。


















