If arrays are passed by reference why should i use int(&)[]

If arrays are passed by reference why should i use int(&)[]


9

#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

  • 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.

    – Klaus

    15 hours ago

  • 2

    Use a const or mutable reference to std::vector or std::array and you will gain both readability and robustness.

    – Friedrich

    15 hours ago


  • Arguably int (&arr)[3] is worse. You can no longer pass std::array<int, 3> to it, nor a part of a larger array. Passing std::span<int, 3> would work around that, but the benefits over a plain pointer are questionable.

    – HolyBlackCat

    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.

    – Konrad Rudolph

    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, or std::array.

    – HolyBlackCat

    14 hours ago

1 Answer
1


22

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.

    – wohlstad

    15 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 Moscow

    15 hours ago




Leave a Reply

Your email address will not be published. Required fields are marked *