The difference is that the third form is more restrictive, while the first and second forms could benefit from a null check.
The first (and second) form can accept an argument that is not an array, as long as the argument converts to an int
pointer.
void changeArray(int array[]) {
array[0] = 1111;
}
int main() {
changeArray(nullptr); // Causes a segmentation fault, but does compile.
}
The third form cannot.
void changeArray(int (&array)[]) {
array[0] = 1111;
}
int main() {
// changeArray(nullptr);
// error: invalid initialization of non-const reference of type 'int (&)[]'
// from an rvalue of type 'std::nullptr_t'
}
An argument that is an array (of int
) would be accepted by any of these functions.
I understood that 1 and 2 are practically the same, passing a pointer to the first element.
Not just practically the same. They are the same. Presumably, that is why you named the second function changeArrayByPointer
instead of changeArray
, since otherwise you'd get a function redefinition error. (If you want to test this out, try putting the declaration void changeArray(int array[]);
before your main function and the definition void changeArray(int *array) { array[0] = 1111; }
after. The definition links to the declaration, despite looking different.) See also Difference between passing array, fixed-sized array and base address of array as a function parameter.
In contrast, the first and third forms are distinct signatures, so they can overload the name changeArray
. (However, if both overloads are in scope, trying to call one with an array argument is ambiguous.)
int (&array)[]
is only valid from c++20. So the question is basically, why c++20 allowed this usage. – Dorsadint (&array)[]
andint& array
are not same in c++. See demo. – Dorsadint array[]
andint *array
are, for function arguments, equivalent (they have different meanings in other contexts). Before C++20,int (&array)[]
is invalid syntax (passing a reference to an array requires an array dimension, which is known at compile time). – HeadedchangeArray(std::span<int>)
to modify (a part of an array), orchangeArray(std::vector<int>&)
or if you know the size of the array at compile time usechangeArray(std::array<int,8>&)
. – Haunch