#include <iostream>
using namespace std;
void Change(int arr[3]) {
for (int i = 0; i < 3; i++) {
arr[i] = 1;
}
}
int Test() {
int arr[3] = { 0, 0, 0 };
for (int i = 0; i < 3; i++) {
cout << arr[i] << endl;
}
Change(arr);
for (int i = 0; i < 3; i++) {
cout << arr[i] << endl;
}
return 0;
}
Since arrays are passed by default as a pointer to their first element and not copied, changing the value of an element of the array in a function effectively results in changing the value of that element of the array in the function caller, which is why the above code outputs
0
0
0
1
1
1
If this is the case then why would anyone need to pass an array like this
void Change(int (&arr)[3])
I am aware that the parentheses are needed to make the argument a reference to an array instaed of an array of references, but what do I gain?
8
1 Answer
This function declaration
void Change(int arr[3]) {
is adjusted by the compiler to
void Change(int *arr) {
So the function knows nothing about the size of the passed array.
If to declare the function like
void Change(int ( &arr )[3]) {
when within the function you can get the size of the array using for example standard function std::size
or get its first and last iterators like std::begin( arr )
and std::end( arr )
. And moreover you can pass the array by reference to a template function that accepts its argument by reference similarly to passing any container..
Another advantage is that the compiler will check that an array of the required size is passed and the user of the function can not pass a null pointer to the functon.
2
-
11
+1. BTW – A nice bonus for using
int ( &arr )[3]
is that you'll get a compiler error if you try to pass an array with the wrong size.– wohlstad15 hours ago
-
3
@wohlstad I have wanted just now to write the same myself appendomg my answer.:) For example in this case you may not pass a null pointer.
– Vlad from Moscow15 hours ago
You may would change the pointer to address a other array or array position? If this is not needed, there is no need to use a ref here.
15 hours ago
Use a
const
or mutable reference tostd::vector
orstd::array
and you will gain both readability and robustness.15 hours ago
Arguably
int (&arr)[3]
is worse. You can no longer passstd::array<int, 3>
to it, nor a part of a larger array. Passingstd::span<int, 3>
would work around that, but the benefits over a plain pointer are questionable.14 hours ago
@HolyBlackCat Except the (fully-featured) alternative is not a plain pointer, it’s a pointer + size, and even then you are foregoing a compile-time assertion that the size is correct.
14 hours ago
@KonradRudolph If you want the assertion,
span
is probably the better option, since it checks the size if given an array, but at the same time can be given a subarray or a larger array, orstd::array
.14 hours ago