6

I was given a (C++) code where arrays are passed using

void fun(int *& name){...}

but what is the idea behind that? I guess it means "an array of references" but when you just pass a pointer to the first element that would be fine, wouldn't it? So what is the motivation to do it this way?

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
Hagadol
  • 362
  • 1
  • 3
  • 16
  • 3
    It means reference of a pointer variable. The purpose is to change the pointer variable passed to it. – πάντα ῥεῖ Aug 29 '14 at 07:04
  • 3
    Arrays? It is not possible to pass actual array objects through such parameter. What you can pass is a *pointer* that points to some array element, but not the array itself. For example, you won't be able to directly pass an `int a[10]` array to this function. – AnT stands with Russia Aug 29 '14 at 07:13
  • It is important to know that **arrays are not pointers, and pointers are not arrays**. See [**this post**](http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in-c) for more on that. – juanchopanza Aug 29 '14 at 08:33

2 Answers2

5

The function receives a reference to a pointer. This means that the function can not only modify the int that is pointed to by name, but also that changes to the pointer itself made within the function call will also be visible outside.

Example:

#include <iostream>

int* allocate()
{
    return new int();
}

void destroy(int*& ptr)
{
    delete ptr;
    ptr = NULL;
}

int
main(int argc, char *argv[])
{
    int* foo = allocate();

    std::cout << foo << std::endl;

    destroy(foo);

    std::cout << foo << std::endl;

    return 0;
}

Output is:

0x82dc008
0
oxygene
  • 621
  • 4
  • 14
2

It means that the function can modify the value of the pointer in the caller.

i.e.

myName* foo; /* ToDo - initialise foo in some way*/
fun(foo);
/* foo might now point to something else*/

I regard this as an anti-pattern. The reason being that people reading your code will not expect foo to be modified in such a way since the calling syntax is indistinguishable from the more normal function void anotherFun(int * name){...}.

The stability of such code can suffer. As such, I'd recommend your using void fun(int ** name){...}. The calling syntax then becomes fun(&foo) which indicates to the function user that foo might be modified.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    I would say it is an anti-pattern to use a pointer when you can use a reference. But I would do something different too: `int* fun(int* name);`, and return the new value. – juanchopanza Aug 29 '14 at 07:19
  • Well, I personally don't like the pointer to pointer syntax where it is not really needed. So it depends on personal preference. However, I agree that in general it might come unexpected to the caller that the pointer can be modified. An alternative to using `int**` as you propose is to have a clear and well documented API with well chosen names for the functions, e.g. `deleteAndSetNull(int*& ptr)` for a function that deletes a pointer and sets it to NULL. – oxygene Aug 29 '14 at 07:19
  • It's funny how divisive this is: I obviously respect your opinion and like the proposal to use `int* fun(int* name)`. I dislike references used in the way the OP has as they make code hard to read and bugs can be introduced by juniors working on collaborative projects. At least use a `const &` if possible. – Bathsheba Aug 29 '14 at 07:26
  • If you want to ensure that `foo` wouldn't be modified, you can use `fun(myName *const &name)` – PaperBirdMaster Aug 29 '14 at 09:20
  • @PaperBirdMaster: Indeed and good advice indeed if taking a value copy is expensive. (In this case though taking a reference will be slower than passing by value unless the compiler optimises out the internal reference counts). – Bathsheba Aug 29 '14 at 09:27