C++数组传参的三种方式及int (&array)[]传参的疑问
你对前两种传参方式的理解没错——void changeArray(int array[])和void changeArrayByPointer(int *array)本质完全一致,都会把数组退化为指向首元素的指针,丢失原数组的长度信息,函数内部操作的都是指针指向的内存。
下面说说int (&array)[]这类数组引用传参的核心区别,以及适用场景:
核心区别
类型与长度信息的保留
指针方式的参数会丢失数组的长度属性,函数内部无法直接得知原数组的大小,必须额外传递长度参数才能安全操作。而数组引用(通常会指定长度,比如int (&array)[5])会完整保留数组的类型信息,包括它的长度。编译器能在编译期识别出这是一个固定长度的数组引用。编译期安全校验
数组引用传参时,编译器会严格检查传入的实参必须是同长度、同类型的数组。如果误传了单个变量的地址、其他长度的数组,或者指针,都会直接触发编译错误,从源头避免了类型不匹配导致的越界风险。而指针方式没有这个限制,任何int*类型的值都能传入,很容易埋下隐患。语义更明确
就像你最初的理解,数组引用的写法直接传递了“操作原数组、无拷贝”的语义——阅读代码的人一眼就能明白,这个函数接收的是数组本身的引用,不会做任何拷贝操作,而且参数必须是数组,不是任意指针,代码意图更清晰。
何时使用数组引用传参
- 需要编译期确保数组长度匹配:如果你写的函数是专门处理固定长度数组的(比如处理一个包含3个坐标值的数组),用
int (&array)[3]作为参数,能强制要求调用者传入长度为3的int数组,避免传错数组长度导致的逻辑错误。 - 需要在函数内部直接获取数组长度:因为保留了数组类型,你可以在函数内部直接用
sizeof(array)/sizeof(array[0])或者C++11及以后的std::size(array)获取数组的编译期长度,不需要额外传递长度参数。 - 追求代码语义清晰:当你想明确告诉其他开发者,这个函数的参数是数组而非指针,且操作的是原数组时,数组引用的写法比指针方式更直观,提升代码的可读性和维护性。
补充:关于int (&array)[]的写法
你写的int (&array)[]属于不完整类型的引用,实际编译时可能会报错,因为数组的长度是其类型的一部分。通常我们会写成带具体长度的形式,或者用模板来适配任意长度的数组:
template <size_t N> void changeArray(int (&array)[N]) { array[0] = 1111; // 可以直接使用N作为数组的长度,比如遍历 for (size_t i = 0; i < N; ++i) { // 对array[i]进行操作 } }
这种模板版本可以适配任意长度的int数组,同时保留编译期的类型检查和长度信息,实用性更强。
内容的提问来源于stack exchange,提问作者LifeIsAscam

