11

In school, our lecturer taught us that the entire array was passed by reference when we pass it to a function,.

However, recently I read a book. It says that arrays are passed by pointer by default when passing the entire array to a function. The book further mention that "passing by pointer is very similar to passing by reference", which means that passing by pointer and passing by reference are actually different.

It appears that different source stated differently.

So my question is: In C++, are arrays passed by reference or by pointer when we pass the entire array to a function?

For Example:

void funcA(int []); //Function Declaration

int main()
{
    int array[5];
    funcA(array); //Is array passed by ref or by pointer here?
}
user3437460
  • 17,253
  • 15
  • 58
  • 106

3 Answers3

32

At worst, your lecturer is wrong. At best, he was simplifying terminology, and confusing you in the process. This is reasonably commonplace in software education, unfortunately. The truth is, many books get this wrong as well; the array is not "passed" at all, either "by pointer" or "by reference".

In fact, because arrays cannot be passed by value due to an old C restriction, there is some special magic that happens with arrays as function arguments.

The function declaration:

void funcA(int[]);

is silently translated into the following:

void funcA(int*);

and when you write this:

funcA(myArray);

it is silently translated into the following:

funcA(&myArray[0]);

The result is that you're not passing the array at all; you pass a pointer to its first element.

Now, at certain levels of abstraction/simplification, you can call this "passing an array by pointer", "passing an array by reference" or even "passing a handle to an array", but if you want to talk in C++ terms, none of those phrases are accurate.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Your comment is a bit confusing. It's sounds like the array is converting to something when it's passed. However the array is always a pointer to the first element, even before passing it. – Melkon Jun 05 '14 at 10:04
  • 7
    @Melkon: No, wrong. An array is an array is an array. _Arrays are not pointers._ – Lightness Races in Orbit Jun 05 '14 at 10:06
  • 3
    @Melkon: No, no it is not. It is an array. Array-to-pointer decay only happens in some very well-specified situations. – Puppy Jun 05 '14 at 10:08
  • 1
    @Melkon: if the array IS a pointer to the first element, where are all the others? (The verb IS means something to me ...). The array is a "packed sequence of identical elements". That decay into a pointer when passed as an argument. The fact that you can use pointer arithmetic to access the array elements (a[5] is nothing more than *(a+5)) does not make the pointer to become the array. They sit in memory into well different places. – Emilio Garavaglia Jun 05 '14 at 10:10
  • @EmilioGaravaglia When an array decays into a pointer, that pointer does not live anywhere in memory unless you explicitly store it in a variable. – fredoverflow Jun 05 '14 at 10:11
  • @LightnessRacesinOrbit Mind elaborating why you say I `pass a pointer to its first element` while `funcA(&myArray[0]);` looks like it is passing by reference? Thanks! – user3437460 Jun 05 '14 at 10:12
  • @FredOverflow: Well that's a little far-fetched. If it doesn't exist in memory then how does the computer access it? From the cloud, magically passing all electronic data-holding devices? – Lightness Races in Orbit Jun 05 '14 at 10:12
  • @user3437460: `funcA(&myArray[0])` has nothing to do with references! The symbol `&` has three meanings: (1) "bitwise AND", (2) "reference type", as in `int&`, (3) "address-of operator" as in `&myIntVariable`. The latter is what's going on here. It gives you a pointer; no references in sight. Silly decision to use the same symbol for so many things, perhaps. – Lightness Races in Orbit Jun 05 '14 at 10:13
  • @LightnessRacesinOrbit Maybe I should have said that the pointer is a prvalue. That is, `&(a + 0)` will not compile. – fredoverflow Jun 05 '14 at 10:14
  • @FredOverflow: That's better :P – Lightness Races in Orbit Jun 05 '14 at 10:15
  • 1
    @FredOverflow: By a memory stand point, function parameter are local variables... And if not "stored" in something having a name,it leave as a "temporary object" in a somewhat "temporary memory" that can be the stack itself or a CPU register. But always "memory" is. Otherwise you cannot use its value (and hence you cannot dereference it) – Emilio Garavaglia Jun 05 '14 at 10:16
  • @FredOverflow When an array is converted to a pointer, that pointer is an rvalue, like the results of any other conversion. While that means that you cannot take its address, that doesn't mean that a compiler can't put it in memory. – James Kanze Jun 05 '14 at 10:18
  • 1
    @Mehrdad: In a question asking whether the lecturer or book is wrong, it _absolutely_ "adds something" to analyse the statements of both the lecturer and the book. Please don't remove crucial parts of my answer. – Lightness Races in Orbit Jun 05 '14 at 10:19
  • So much for trying to make your post better. *"This is reasonably commonplace in software education, unfortunately."* is unnecessary commentary. Just answer the question. – user541686 Jun 05 '14 at 10:19
  • 1
    @Mehrdad: No, it's not "unnecessary". It's important for the OP to know that he will encounter these myths and lies a lot in education, so that he knows it is okay to ignore them. Why are you deliberately trying to stifle the truth? That's really suspicious. Meanwhile, your answer barely makes any sense so perhaps concentrate on that for a while. – Lightness Races in Orbit Jun 05 '14 at 10:20
  • *"That's really suspicious."* ...what, you think I'm the lecturer or something? Why am I even wasting my time on you... – user541686 Jun 05 '14 at 10:22
  • 1
    @Mehrdad: I dunno, maybe a member of the illuminati, or the founder of some anti-C++ religious order... who knows?! BTW please stop being so rude; _that_ is "unnecessary". – Lightness Races in Orbit Jun 05 '14 at 10:23
  • @LightnessRacesinOrbit: Damn, my cover just got blown. :( – user541686 Jun 05 '14 at 10:25
  • @Mehrdad: Will they be sending a new agent to take your place? I do sincerely hope the ritual beheading is quick and painless. :( – Lightness Races in Orbit Jun 05 '14 at 10:31
4

The terminology used by your lecturer is confusing. However, in a function declaration such as

void funcA(int []);

the int[] is just another way of saying int*. So funcA can take any argument that is or can be converted to an int*.

Arrays can decay to pointers to the first element in the right context. This means, for example, that you can assign an array's name to a pointer like this:

int array[42];  // array is of type int[42]
int * arr = array; // array decays to int*

So, when you pass array to funcA,

funcA(array); // array decays to int*

funcA has a pointer to the first element of the array.

But it is also possible to pass arrays by reference. It just requires a different syntax. For example

void funcB(int (&arr)[42]);

So, in your example, you are passing a pointer to the first element of the array, due to the signature of your function funcA. If you called funcB(array), you would be passing a reference.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

Pass-by-pointer is a bit of a misnomer. It doesn't happen in C++. There is only pass-by-value and pass-by-reference. Pointers in particular are passed by value.

The answer to your question is: it depends.

Consider the following signatures:

void foo(int *arr);
void bar(int *&arr);
void baz(int * const &arr);
void quux(int (&arr)[42]);

Assuming you are passing an array to each of these functions:

  • In foo(arr), your array is decayed to a pointer, which is then passed by value.
  • In bar(arr), this is a compiler error, because your array would decay to a (temporary) pointer, and this would be passed by reference. This is nearly always a bug, since the reason you would want a mutable reference is to change the value of the referent, and that would not be what would happen (you would change the value of the temporary instead). I add this since this actually does work on some compilers (MSVC++) with a particular extension enabled. If you instead decay the pointer manually, then you can pass that instead (e.g. int *p = arr; bar(p);)
  • In baz(arr), your array decays to a temporary pointer, which is passed by (const) reference.
  • In quux(arr), your array is passed by reference.

What your book means by them being similar is that passing a pointer by value and passing a reference are usually implemented identically. The difference is purely at the C++ level: with a reference, you do not have the value of the pointer (and hence cannot change it), and it is guaranteed to refer to an actual object (unless you broke your program earlier).

Kaz Dragon
  • 6,681
  • 2
  • 36
  • 45