Slava V
Slava V

Reputation: 17256

C++: difference between ampersand "&" and asterisk "*" in function/method declaration?

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?

Upvotes: 85

Views: 83911

Answers (7)

RnR
RnR

Reputation: 2115

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.

Upvotes: 1

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506955

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.

Upvotes: 1

Charlie Martin
Charlie Martin

Reputation: 112366

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.

Upvotes: 35

jmucchiello
jmucchiello

Reputation: 18984

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.

Upvotes: 6

finnw
finnw

Reputation: 48619

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.

Upvotes: 4

Greg Hewgill
Greg Hewgill

Reputation: 993085

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);

Upvotes: 6

Brian R. Bondy
Brian R. Bondy

Reputation: 347216

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

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

Upvotes: 64

Related Questions