Difference between function arguments declared with & and * in C++
Solution 1
f2
is taking it's arguments by reference, which is essentially an alias for the arguments you pass. The difference between pointer and reference is that a reference cannot be NULL. With the f
you need to pass the address (using & operator) of the parameters you're passing to the pointer, where when you pass by reference you just pass the parameters and the alias is created.
Passing by const reference (const double& ref
) is preferred when you are not going to change the arguments inside the function, and when you are going to change them, use non-const reference.
Pointers are mostly used when you need to be able to pass NULL
to your parameters, obviously you'd need to check then inside your function if the pointer was not NULL
before using it.
Solution 2
This is just syntactic sugar to avoid having to use *
everytime you reference the argument. You still can use &
to have the address of x
in f2
.
Solution 3
Another difference that hasn't been mentioned is that you cannot change what a reference refers to. This doesn't make a lot of difference in the function call example shown in the original question.
int X(10), Y(20);
int *pX = X;
int& rY = Y;
*pX = 15; // change value of X
rY = 25; // change value of Y
pX = Y; // pX now points to Y
rY
always points to Y
and cannot be moved.
References can't be used to index into simple arrays like pointers.
Solution 4
In my head, parameters of functions are always passed by value. Passing an int
is easy to imagine, passing a double
is just bigger and passing a struct
or class
could be very big indeed.
But passing a pointer to something, well, you're just passing an address by value. (A pointer is often a convenient size for the CPU just like an int
.)
A reference is very similar, and certainly I think of a reference as a pointer, but with syntactic sugar to make it look like the object its referring to has been passed by value.
You can also think of a reference as a const
pointer, ie:
int i;
int j;
int* p = &i; // pointer to i
int* const cp = p; // cp points to i, but cp cannot be modified
p = &j; // OK - p is modified to point to j
*cp = 0; // OK - i is overwritten
cp = &j; // ERROR - cp cannot be modified
int& ri = i; // ri refers to i
ri = 1; // i is overwritten
ri = j; // i is overwritten again
// Did you think ri might refer to j?
So, a pointer does double time: It is a value in its own right, but it can also point to another value when you dereference it, eg: *p
.
Also, having reference parameters means that you cannot make them refer to anything else during the lifetime of the function because there's no way to express that.
A reference is supposed not to be able to be initialised with null
, but consider this:
void foo(int& i);
int* p = 0;
foo(*p);
This means that pointers should be checked before you use them, but references cannot be checked. The implementation of foo()
could try to read from or write to i
which will cause an access violation.
In the above example the pointer p
should have been checked before being used in the call to foo
:
if (p) foo(*p);
Solution 5
You should have been able to read x
address in both functions.
To do so in f2
, you must of course prefix x
by a &
since there, x
is a reference to a double, and you want an address.
A worth noticing difference between references and pointers is that the former cannot be NULL. You must pass something (valid) while when providing a pointer, you must specify in the documentation if passing NULL is allowed/well defined.
Another difference is a matter of readability: using references instead of pointers (when possible) makes the code less cluttered with *
and ->
.
Comments
-
tim about 4 years
I typed the following example:
#include <iostream> double f(double* x, double* y) { std::cout << "val x: " << *x << "\n"; std::cout << "val y: " << *y << "\n"; return *x * *y; } double f2(double &x, double &y) { std::cout << "val x: " << x << "\n"; std::cout << "val y: " << y << "\n"; return x * y; } int main() { double a, b; a = 2; b = 3; std::cout << f(&a, &b) << "\n"; std::cout << f2(a, b) << "\n"; return 0; }
In the function
f
I declare x and y as pointers of which I can get the value by using*x
. When callingf
I need to pass the address of my passed arguments, that is why I pass&a, &b
.f2
is the same except the definition is different.Now my question is: Are they both really the same concerning memory management? Both not making any copy of the passed value but instead passing a reference? I wonder about
f2
because I couldn't read out the address ofx
inf2
so I know more about x and y inf
(there I know address AND value).Thanks in advance!
Edit: Okay thanks, after doing some more research, I found a quite useful topic:
Pointer vs. Reference There's also a link to google coding guidelines http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments which is quite
useful
I feel (as I understood now, it's a form of subject taste) to make more clear -
Len Holgate about 13 yearsPersonally I think it's more than just that. It states that the argument CANNOT be null and is NOT optional. With pointers you can never tell and must always check. With references the function signature enforces the programmer's intent and leads to cleaner code which more accurately reflects that intent.
-
Mike Seymour about 13 yearsAlso, a pointer argument might expect an array. A reference argument specifically takes one single object, with no further documentation required.
-
Weloo about 10 yearsWhy does someone need to pass Null to the parameters?
-
Ludwik almost 10 yearsWell they probably need to be able to pass null if needed. Obviously they're not going to pass it all the time.
-
pfabri over 7 yearsThis is really very helpful, excellent examples. Perhaps you could add a comment to your
void foo(int& i);
example to say what exactly is wrong with calling it with aNULL
pointer. -
LXSoft over 6 yearsQ: "The difference between pointer and reference is that a reference cannot be NULL". The most simple and clear answer, when you should and when not use * vs & as function arguments. An alias never can be NULL.
-
Aaron Franke over 3 yearsWhat is the difference between
f2
and doing the same thing but without&
so it's likedouble f3(double x, double y)
? -
Mauricio Cortazar about 2 years@AaronFranke so you don't duplicate data in memory