Arrays of references

Hello there! I have a question that may be pretty trivial but I really have no idea whom or where else to ask it, so I thought the beginners forums here would be a good idea.

I don't really have any clue how to explain this in words, so I'll just do it in a few examples.

OK, to take a very simple example, if we have the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

int n;

void incr(int &x)
{
    x++;
}

main()
{
    cin>>n;
    incr(n);
    cout<<n;
}


the program takes an integer and prints out its successor, whereas if we had

1
2
3
4
void incr(int x)
{
    x++;
}


instead of

1
2
3
4
void incr(int &x)
{
    x++;
}


the program would just take a number and print out the same number.

Now I'm sure everybody here already knows that, but I needed that to get to my point. So if we have the same thing with arrays instead of simple variables, if I try to implement the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

using namespace std;

int g[101],m;

void caca(int &a[101],int n)
{
    for(int i=1;i<=n;i++)
        a[i]=a[i]+1;
}

int main()
{
    cin>>m;
    for(int i=1;i<=m;i++)
        cin>>g[i];
    caca(g,m);
    for(int i=1;i<=m;i++)
        cout<<g[i]<<" ";
    cout<<endl;
}


it just gives me an error on line 7: "declaration of 'a' as array of references". I've googled an explanation for this and I more or less got why this happens. This is not why I am posting this. My problem is the following: after I've removed the '&' in front of a[101], so as we now have this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

using namespace std;

int g[101],m;

void caca(int a[101],int n)
{
    for(int i=1;i<=n;i++)
        a[i]=a[i]+1;
}

int main()
{
    cin>>m;
    for(int i=1;i<=m;i++)
        cin>>g[i];
    caca(g,m);
    for(int i=1;i<=m;i++)
        cout<<g[i]<<" ";
    cout<<endl;
}


the program is doing what I wanted it to do initially. It takes every integer in the array g and prints out its successor. My question is: why does it do that? Why are all of the values of the array a exported to g even though it is not declared as a reference? (or to put it better, it cannot be declared as a reference) What if I wanted not to export the values of a into g? What if I wanted to make a subprogram that takes g as a parameter, makes some modifications to a inside a subprogram but leaves it unchanged? For instance, if you wanted to make a program that prints out the maximum integer from an array of integers, then prints the array itself, one way you could do it would be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

using namespace std;

int g[101],m,maxx;

void sorto(int a[101],int n)
{
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
            if(a[i]>a[j])
            {
                a[i]=a[i]+a[j];
                a[j]=a[i]-a[j];
                a[i]=a[i]-a[j];
            }
    maxx=a[n];
}

int main()
{
    cin>>m;
    for(int i=1;i<=m;i++)
        cin>>g[i];
    sorto(g,m);
    cout<<maxx<<endl;
    for(int i=1;i<=m;i++)
        cout<<g[i]<<" ";
    cout<<endl;
}


but you can't do this because g will retain all of the changes made during sorto(), despite a not being preceded by an & sign.
NOTE: I know there are many other (way simpler and more elegant) ways of doing what I just said, but that's not the point. I've just tried to give an example of what I mean since I'm usually not very good at explaining things.

So to sum it all up, I guess my question would be: why does C++ export the changes made to the parameter of a function (a in our case) into the value it takes (g in our case) even though it is not preceded by an & sign, if said parameter is an array?

If you've read through all of this, thank you. I know I've provided many potentially useless information but I just wanted to make my point clear. An answer would be greatly appreciated.
why does C++ export the changes made to the parameter of a function (a in our case) into the value it takes (g in our case) even though it is not preceded by an & sign, if said parameter is an array?


Because the array type on a by-value function parameter is a lie: it is actually a pointer type.

1
2
3
4
5
//These four declarations declare the same exact function:
void caca(int a[101123],int n)
void caca(int a[101],int n)
void caca(int a[],int n)
void caca(int *a,int n)


And the reason for that is that C did it, and C did it because arrays are not copyable for compatibility with B (unless wrapped inside structs, which were a C invention).

If you use C++ arrays, things are as you'd expect

1
2
void caca(std::array<int, 101> a) // pass by value, changes are not "exported" back to the caller
void caca(std::array<int, 101>& a) // pass by reference 


(by the way, you can also pass a C array by reference with
 
void caca(int (&a)[101])
)
Last edited on
Topic archived. No new replies allowed.