82

Is there some kind of subtle difference between those:

void a1(float &b) {
    b=1;
};
a1(b);

and

void a1(float *b) {
    (*b)=1;
};
a1(&b);

?

They both do the same (or so it seems from main() ), but the first one is obviously shorter, however most of the code I see uses second notation. Is there a difference? Maybe in case it's some object instead of float?

Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
Slava V
  • 16,686
  • 14
  • 60
  • 63
  • 1
    Now try to figure out what void a1(float &&b) means in C++0x. :) – Daniel Earwicker Feb 27 '09 at 21:09
  • It would be nice to also have it explained why a LHS & might be preferable to * in some situations, or even necessary at all if we have * for references. – T. Webster Jan 31 '11 at 01:06
  • @T.Webster: References are immutable. That means that when you make one it definitely refers to something (so can not be NULL, the compiler forces you to explicitly specify what it will refer to), and once you have made it it can never be made to refer to anything else. They're safer because you can't accidentally do silly things like pointer arithmetic when you didn't meant to. – Sam Svenbjorgchristiensensen May 09 '13 at 04:12
  • possible duplicate of [What are the differences between a pointer variable and a reference variable in C++?](http://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in) – Flow May 06 '15 at 15:18
  • 1
    @Flow I think that this question should remain, since I was searching for this exact point, and wouldn't have known that one referred to pointers and one referred to passing by reference unless I had visited this page. Thanks for the link to the other question though! – Resquiens Dec 05 '15 at 19:50
  • Closing as duplicate won't delete this question. Stackechange's de-duplication mechanism was designed with this case in mind. – Flow Dec 05 '15 at 20:02

7 Answers7

64

Both do the same, but one uses references and one uses pointers.

See my answer here for a comprehensive list of all the differences.

Community
  • 1
  • 1
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 1
    Upvoted too, not my "-1". Maybe someone felt this didn't explain enough. Thanks for the answer! – Slava V Feb 27 '09 at 20:54
  • Great post, been struggling for a few hours now and after reading your summary I got blessed with a "Eureka"-moment ;) Thanks @DanielSloof ! – polyclick Jul 25 '12 at 19:25
  • 29
    I would consider down voting this on account of it being nothing more than a link. Answers on SO are supposed to stand entirely on their own with links being used as support/reference - not as the entire answer. As it is, I'm not down voting this because it points at another SO answer, which nullifies my big issue with posting links as issues: websites can and do change or go down over the years! But of course if one answer were to go down, it seems probable the other would as well, so I'll let it pass and simply not vote on it. – ArtOfWarfare Jan 07 '13 at 23:38
35

Yes. The * notation says that what's being pass on the stack is a pointer, ie, address of something. The & says it's a reference. The effect is similar but not identical:

Let's take two cases:

   void examP(int* ip);
   void examR(int& i);

   int i;

If I call examP, I write

   examP(&i);

which takes the address of the item and passes it on the stack. If I call examR,

   examR(i);

I don't need it; now the compiler "somehow" passes a reference -- which practically means it gets and passes the address of i. On the code side, then

   void examP(int* ip){
        *ip += 1;
   }

I have to make sure to dereference the pointer. ip += 1 does something very different.

   void examR(int& i){
        i += 1;
   }

always updates the value of i.

For more to think about, read up on "call by reference" versus "call by value". The & notion gives C++ call by reference.

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • Charlie Martin or someone who understands this answer, would you please reword/rewrite this to be a more concise answer? Specifically the two example cases. I believe there is valuable information here and I believe this answer and users would benefit from a more concise answer. I'd edit the answer myself, but I do not understand the two example cases. – HappyCoding Nov 07 '17 at 17:24
  • I think you'd do better to read Stroustrup. I don't blame you for being confused. – Charlie Martin Nov 08 '17 at 16:09
6

In the first example with references, you know that b can't be NULL. With the pointer example, b might be the NULL pointer.

However, note that it is possible to pass a NULL object through a reference, but it's awkward and the called procedure can assume it's an error to have done so:

a1(*(float *)NULL);
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
6

Aside from syntactic sugar, the only real difference is the ability for a function parameter that is a pointer to be null. So the pointer version can be more expressive if it handles the null case properly. The null case can also have some special meaning attached to it. The reference version can only operate on values of the type specified without a null capability.

jmucchiello
  • 18,754
  • 7
  • 41
  • 61
4

In the second example the caller has to prefix the variable name with '&' to pass the address of the variable.

This may be an advantage - the caller cannot inadvertently modify a variable by passing it as a reference when they thought they were passing by value.

finnw
  • 47,861
  • 24
  • 143
  • 221
1

Functionally in your example, both versions do the same.

The first has the advantage that it's transparent on the call-side. Imagine how it would look for an operator:

cin >> &x;

And how it looks ugly for a swap invocation

swap(&a, &b);

You want to swap a and b. And it looks much better than when you first have to take the address. Incidentally, bjarne stroustrup writes that the major reason for references was the transparency that was added at the call side - especially for operators. Also see how it's not obvious anymore whether the following

&a + 10

Would add 10 to the content of a, calling the operator+ of it, or whether it adds 10 to a temporary pointer to a. Add that to the impossibility that you cannot overload operators for only builtin operands (like a pointer and an integer). References make this crystal clear.

Pointers are useful if you want to be able to put a "null":

a1(0);

Then in a1 the method can compare the pointer with 0 and see whether the pointer points to any object.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • swap(int&a, int&b) cannot determine that the call was made with identical arguments: swap(x, x); and jump out early. The pointer version can: if (a == b) return; Not sure that important but it is a case the reference version cannot handle. – jmucchiello Feb 27 '09 at 20:56
  • joe, it can: if(&a == &b) return; – Johannes Schaub - litb Feb 27 '09 at 20:59
1

One big difference worth noting is what's going on outside, you either have:

a1(something);

or:

a1(&something);

I like to pass arguments by reference (always a const one :) ) when they are not modified in the function/method (and then you can also pass automatic/temporary objects inside) and pass them by pointer to signify and alert the user/reader of the code calling the method that the argument may and probably is intentionally modified inside.

RnR
  • 2,096
  • 1
  • 15
  • 23