Is pass-by-value/reference defined implementation or behavior wise? - c++

Q: Is pass-by-value/reference defined strictly by behavior or implementation wise in C++, and can you provide an authoritative citation?
I had a conversion with a friend about pass-by-value/reference in C++. We came to a disagreement on the definition of pass-by-value/reference. I understand that passing a pointer to a function is still pass-by-value since the value of the pointer is copied, and this copy is used in the function. Subsequently, dereferencing the pointer in the function and mutating it will modify the original variable. This is where the disagreement appears.
His stance: Just because a pointer value was copied and passed to the function, performing operations on the dereferenced pointer has the ability to affect the original variable, so it has the behavior of pass-by-reference, passing a pointer to a function.
My stance: Passing a pointer to a function does copy the value of the pointer, and operations in the function may affect the original variable; however, just because it may affect the original, this behavior does not constitute it to be pass-by-reference since it is the implementation of the language that is what defines these terms, pass-by-value/reference.
Quoting from the definition given by the highest voted answer here: Language Agnostic
Pass by Reference
When a parameter is passed by reference, the caller and the callee use the same variable for the parameter. If the callee modifies the parameter variable, the effect is visible to the caller's variable.
Pass by Value
When a parameter is passed by value, the caller and callee have two independent variables with the same value. If the callee modifies the parameter variable, the effect is not visible to the caller.
I still have an ambiguous feeling after reading these. For example, the pass by value/reference quotes can support either of our claims. Can anyone clear up the definitions of whether these definition stem from behavior or implementation and provide a citation? Thanks!
Edit: I should be a little more careful of my vocabulary. Let me extend my question with a clarification. What I mean when questioning pass-by-reference is not talking purely about the C++ implementation of & reference, but instead also the theory. In C++, is it that the & pass-by-reference is true PBR because not only can it modify the original value, but also the memory address of the value. This leads to this, example with pointers also count as PBR?
void foo(int ** bar){
*bar = *bar+(sizeof(int*));
cout<<"Inside:"<<*bar<<endl;
}
int main(){
int a = 42;
int* ptrA = &a;
cout<<"Before"<<ptrA<<endl;
foo(&ptrA);
cout<<"After:"<<ptrA<<endl;
}
The output would be that After ptrA is equal to Inside, meaning that not only can the function modify a, but ptrA. Because of this, does this define call-by-reference as a theory: being able to not only modify the value, but the memory address of the value. Sorry for the convoluted example.

You talk a lot about pointers here, which they are indeed passed by value most of the time, but you don't mention actual C++ references, which are actual references.
int a{};
int& b = a;
// Prints true
std::cout << std::boolalpha << (&b == &a) << std::endl;
Here, as you can see, both variables have the same address. Put it simply, especially in this case, references act as being another name for a variable.
References in C++ are special. They are not objects, unlike pointers. You cannot have an array of references, because it would require that references has a size. Reference are not required to have a storage at all.
What about actually passing a variable by reference then?
Take a look at this code:
void foo(int& i) {
i++;
}
int main() {
int i{};
foo(i);
// prints 1
std::cout << i << std::endl;
}
In that particular case, the compiler must have a way to send to which variable the reference is bound. Indeed references are not required to have any storage, but they are not required to not have one either. In this case, if optimizations are disabled, it is most likely that the compiler implements the behavior of references using pointers.
Of course, if optimizations are enabled, it may skip the passing and completely inline the function. In that case, the reference don't exist, or don't have any storage, because the original variable will be used directly.
Other similar optimization happens with pointers too, but that's not the point: The point is, the way references are implemented is implementation defined. They are most likely implemented in term of pointers, but they are not forced to, and the way a reference is implemented may vary from case to case. The behavior of references are defined by the standard, and really is pass-by-reference.
What about pointers? Do they count as passing by reference?
I would say no. Pointers are objects, just like int, or std::string. You can even pass a reference to a pointer, allowing you to change the original pointer.
However, pointers do have reference semantics. They are not reference indeed, just like std::reference_wrapper is not a reference either, but they have reference semantics. I wouldn't call passing a pointer "passing by reference", because you don't have an actual reference, but you indeed have reference semantics.
A lot of things have reference semantics, pointers, std::reference_wrapper, a handle to a resource, even GLuint, which are handle to an opengl object, all have reference semantics, but they are not references. You don't have a reference to the actual object, but you can change the pointed-to object through these handles.
There are other good articles and answers you can read about. They are all very informative about value and reference semantics.
isocpp.org: Reference and Value Semantics
Andrzej's C++ blog: Value semantics
Stack Overflow: What are the differences between a pointer variable and a reference variable in C++?

Passing by value/reference (you forgot one which is passing the address to the location in memory by using a pointer) is part of the implementation of C++.
There is one more way to pass variables to functions, and that is by address. Passing an argument by address involves passing the address of the argument variable (using a pointer) rather than the argument variable itself. Because the argument is an address, the function parameter must be a pointer. The function can then dereference the pointer to access or change the value being pointed to.
Take a look here at what I have always thought to be an authoritative Source: Passing Arguments by Address.
You're correct in regards to a value being copied when passing by value. This is the default behavior in C++. The advantage of passing by value into a function is that the original value cannot be changed by the function when the value is passed into it and this prevents any unwanted bugs and/or side effects when changing the value of an argument.
The problem with passing by Value is that you will incur a huge performance penalty if you pass an entire struct or class many times into your function as you will be passing entire copies of the value you are trying to pass AND in the case of a mutator method in a class, you will not be able to change the original values and will therefore end up creating multiple copies of the data you are trying to modify because you will be forced to return the new value from the function itself instead of from the location in memory where the data structure resides. This is just completely inefficient.
You only want to pass by value when you don't have to change the value of the argument.
Here is a good source on the topic of Passing Arguments by Value.
Now, you will want to use the "Pass by Reference" behavior when you do need to change the value of an argument in the case of arrays, Classes, or structs. It is more efficient to change the value of a data structure by Passing a Reference to the location in memory where the data structure resides into the function. This has the benefit that you will not have to return the new value from the function but rather, the function can then change the value of the reference you have given it directly where it resides in memory.
Take a look here to read more about about Passing an Argument by Reference.
EDIT: In regards to the issue as to whether or not you are passing a non-const by reference or by value when using a pointer, it seems to me the answer is clear. When using a pointer to a non-const, it is neither. When passing a pointer as an argument to a function, you in fact are "Passing the Value" of the ADDRESS into the function and since it is a copy of the ADDRESS of the location in memory where the non-const resides, then you are able to change the Value of the data at that location and not the value of the pointer itself. If you do not want to change the value of the data located at the address pointed to by the pointer being passed by value as an argument into your function, it is good form to make the pointer to an argument a const since the function will not be changing the value of the data itself.
Hope that makes sense.

References are different from pointers. The main reason references were introduced is to support Operator Overloading. C++ is derived from C and during the process, Pointers were inherited from C. As Stroustrup says:
C++ inherited pointers from C, so I couldn't remove them without causing serious compatibility problems.
So, effectively there are three different ways of parameters passing:
Pass by value
Pass by reference &
Pass by pointers.
Now, pass by pointer has the same effect as pass by reference. So how to decide on what you want to use? Going back to what Stroustrup said:
That depends on what you are trying to achieve:
If you want to change the object passed, call by reference or use a pointer; e.g. void f(X&); or void f(X*);
If you don't want to change the object passed and it is big, call by const reference; e.g. void f(const X&);
Otherwise, call by value; e.g. void f(X);
Ref: http://www.stroustrup.com/bs_faq2.html#pointers-and-references

Those terms are about the variable that is passed, in this case the pointer. If you pass a pointer to a function then the variable that is passed is the pointer - holding the address of the object - to an object and not the object it points to.
If you pass a pointer by value then chaning the object it is pointing to in the function would not affect the pointer that was passed to the function.
If you pass the pointer by reference then you can change in the function where the pointer is pointing to and it would modifiy the pointer that was passed to this function.
Thats how it is defined. Otherwise you could argue that if you have a global std::map<int,SomeObject> and you pass an int as key to the object, would also be a pass by reference because you can modify the objects in that global map, and the caller would see those changes. Because this int is also just a pointer to an object.

Related

C++ conventions regarding passing objects (pointer vs reference)

I'd like to work out conventions on passing parameters to functions/methods. I know it's a common issue and it has been answered many times, but I searched a lot and found nothing that fully satisfies me.
Passing by value is obvious and I won't mention this. What I came up with is:
Passing by non-const reference means, that object is MODIFIED
Passing by const reference means, that object is USED
Passing by pointer means, that a reference to object is going to be STORED. Whether ownership is passed or not will depend on the context.
It seems to be consistent, but when I want to pick heap-allocated object and pass it to 2. case parameter, it'd look like this:
void use(const Object &object) { ... }
//...
Object *obj = getOrCreateObject();
use(*obj);
or
Object &obj = *getOrCreateObject();
use(obj);
Both look weird to me. What would you advise?
PS I know that one should avoid raw pointers and use smart instead (easier memory managment and expressiveness in ownership) and it can be the next step in refactoring the project I work on.
You can use these conventions if you like. But keep in mind that you cannot assume conventions when dealing with code written by other people. You also cannot assume that people reading your code are aware of your conventions. You should document an interface with comments when it might be ambiguous.
Passing by pointer means, that object is going to be STORED. Who's its owner will depend on the context.
I can think of only one context where the ownership of a pointer argument should transfer to the callee: Constructor of a smart pointer.
Besides possible intention of storing, a pointer argument can alternatively have the same meaning as a reference argument, with the addition that the argument is optional. You typically cannot represent an optional argument with a reference since they cannot be null - although with custom types you could use a reference to a sentinel value.
Both look weird to me. What would you advise?
Neither look weird to me, so my advise is to get accustomed.
The main problem with your conventions is that you make no allowance for the possibility of interfacing to code (e.g. written by someone else) that doesn't follow your conventions.
Generally speaking, I use a different set of conventions, and rarely find a need to work around them. (The main exception will be if there is a need to use a pointer to a pointer, but I rarely need to do that directly).
Passing by non-const reference is appropriate if ANY of the following MAY be true;
The object may be changed;
The object may be passed to another function by a non-const reference [relevant when using third party code by developers who choose to omit the const - which is actually something a lot of beginners or lazy developers do];
The object may be passed to another function by a non-const pointer [relevant when using third party code be developers who choose to omit the const, or when using legacy APIs];
Non-const member functions of the object are called (regardless of whether they change the object or not) [also often a consideration when using third-party code by developers who prefer to avoid using const].
Conversely, const references may be passed if ALL of the following are true;
No non-mutable members of the object are changed;
The object is only passed to other functions by const reference, by const pointer, or by value;
Only const member functions of the object are called (even if those members are able to change mutable members.
I'll pass by value instead of by const reference in cases where the function would copy the object anyway. (e.g. I won't pass by const reference, and then construct a copy of the passed object within the function).
Passing non-const pointers is relevant if it is appropriate to pass a non-const reference but there is also a possibility of passing no object (e.g. a nullptr).
Passing const pointers is relevant if it is appropriate to pass a const reference but there is also a possibility of passing no object (e.g. a nullptr).
I would not change the convention for either of the following
Storing a reference or pointer to the object within the function for later use - it is possible to convert a pointer to a reference or vice versa. And either one can be stored (a pointer can be assigned, a reference can be used to construct an object);
Distinguishing between dynamically allocated and other objects - since I mostly either avoid using dynamic memory allocation at all (e.g. use standard containers, and pass them around by reference or simply pass iterators from them around) or - if I must use a new expression directly - store the pointer in another object that becomes responsible for deallocation (e.g. a std::smart_pointer) and then pass the containing object around.
In my opionion, they are the same. In the first part of your post, you are talking about the signature, but your example is about function call.

call by value vs const call by reference

I am a little confused about the differences between call by value and const call by reference. Could someone please explain this to me. For example, do they both protect against changing the callers argument, are they fast for all object sizes, do either copy the argument while one doesnt, and which use more memory when making a copy?
do they both protect against changing the callers argument
Passing by value creates a copy of the argument provided by the caller, so whatever the function does, it does it on a separate objects. This means the original object won't ever be touched, so in this case the answer is "Yes".
Passing by reference to const, on the other hand, lets the function refer the very same object that the caller provided, but it won't let that function modify it... Unless (as correctly remarked by Luchian Grigore in the comments) the function's implementer uses const_cast<> to cast away the const-ness from the reference, which is something that can be safely done only if it is known that the object bound to the reference was not declared to be of a const type (otherwise, you would get Undefined Behavior).
Since this does not seem to be the most likely scenario considering your question, and considering that in general accepting a reference to const represents a promise that the argument won't be touched, then the answer is that as long as we assume this promise to be fulfilled, passing by reference to const won't alter the argument provided by the caller. So the answer is "Yes" again - with the little caveat I mentioned above.
are they fast for all object sizes
No. Although you should first define "fast". If the type of the object being passed is expensive to copy (or to move, if a move is performed rather than a copy), then passing by value might be slow. Passing by reference will always cost you the same (the size of an address), no matter what is the type of the value you are passing.
Notice, that on some architecture and for some data types (like char) passing by value could be faster than passing by reference, while the opposite is generally true for large enough UDTs.
and which use more memory when making a copy?
Since only one of them is causing a copy, the question has an obvious answer.
The main difference is that passing by const reference (or non-const) doesn't make a copy of the argument. (the copy is actually subject to copy elision, but theoretically it's a copy that's passed to the function when you pass by value)
In some cases, passing by value is just as fast, or even faster (typically when the object is at most the size of a register). You'd usually pass basic types by value, and class-types by reference.
When passing by const reference you can still modify the original value just by casting the const away (via const_cast), but that results in undefined behavior if the original value is const.
call by value will copy all the elements of the object it does protect the callers argument because if you are going to change something it is only a copy you are changing.
calling by const reference does not copy elements but because of the "const" it will protect caller's argument.
You const reference.
I suppose that you mean the difference between:
void Fn1(MyType x);
and
void Fn2(const MyType& x);
In former case, a copy of the object is always created, which makes it slower especially if the type has a non-trivial constructor. The original object will be unaffected by any changes done on the copy within the function, but the copy itself can be changed.
The latter example will not create a copy and will in general be faster. Inside the function, only the const functions can be called on the argument (unless you resort to dirty tricks like casting away constness), thus guaranteeing that the object will not be modified.
IMPORTANT: This discussion doesn't cover types with special semantics, like smart pointers. In that case, call by value will still allow you to change what is logically the same object, i.e. not the smart ptr instance itself but the object it points to.
So here are the answers to your questions:
do they both protect against changing the callers argument: yes, the original object will remain unchanged (excluding tricks)
are they fast for all object sizes: they are not equally fast - call by reference is in general faster, except for some primitive types where speed is more or less the same or maybe even marginally faster, depending on compiler optimizations.
do either copy the argument while one doesnt: call by value creates a copy, call by reference doesn't
which use more memory when making a copy? call by reference doesn't create a copy so the answer is clear
One other point worth mentioning is that call-by-reference functions are converted into inline functions.

C++: Why can a statically created variable by passed to a function expecting a reference?

I've been programming in C++ for a while but certainly wouldn't call myself an expert. This question isn't being asked to solve a practical problem that I have, it's more about understanding what C++ is doing.
Imagine I have a function that expects a single paramater:
void doSomething(SomeClass& ref)
{
// do something interesting
}
(Note: the parameter is a reference to SomeClass) Then I call the function like this:
int main(int argc, char *argv[])
{
SomeClass a;
doSomething(a);
}
Why is this legal C++? The function is expecting a reference to SomeClass, but I'm passing it a statically allocated variable of type SomeClass. A reference is like a pointer no? If we were to replace the reference with a pointer the compiler complains. Why is the reference different to a pointer in this way, what's going on behind the scenes?
Sorry if this is a stupid question, it's just been buggin me!
I think you'd understand this better if you stopped thinking of references as being similar to pointers. I would say there are two reasons why this comparison is made:
References allow you to pass objects into functions to allow them to be modified. This was a popular use case of pointers in C.
The implementation of pointers and references is usually pretty much the same once it's compiled.
But they are different things. You could think about references as a way of giving a new name to an object. int& x = y; says that I want to give a new name to the object I currently refer to as y. This new name is x. Both of those identifies, x and y, both refer to the same object now.
This is why you pass the object itself as a reference. You are saying that you want the function to have its own identifier to refer the object that you are passing. If you don't put the ampersand in the parameter list, then the object will be copied into the function. This copying is often unnecessary.
Your code is incorrect - SomeClass a(); is a forward declaration of a function a returning a SomeClass instance - such a declaration is not valid at function scope.
Assuming you meant SomeClass a;:
A reference is quite similar to a pointer in most practical ways - the main difference is that you cannot legally have a reference to NULL, whereas you can have a pointer to NULL. As you've noticed, the syntax for pointers and references is different - you can't pass a pointer where a reference is expected.
If you think of a reference as a "pointer that can't be null and can't be made to point elsewhere" you're pretty much covered. You're passing something which refers to your local a instance - if doSomething modifies its parameter then it's really directly modifying your local a.
SomeClass a();
This is a function signature, not an object.
It should be
SomeClass a; // a is an object
Then your code is valid.
Why is this legal C++?
(assuming you fixed the previous point)
C++ standard say that if your function attribute is a reference, then you should provide an object that have a name (an l-value). So here, it's legal. If it was a const reference, you could even provide a temporary (an r-value, that have no name).
The function is expecting a reference
to SomeClass, but I'm passing it a
statically allocated variable of type
SomeClass.
It's expecting a reference to an non-const instance of SomeClass, that is what you did provide.
That instance is not static, it's just allocated on the stack. The allocation of an object have nothing to do with the way it can be manipulated, only the scope does. The way the object is alloced (on the stack like here, or on the heap by using new/delete) only tells the lifetime of the object. Even a static object could be passed in your function, as far as it's not const.
I think you're mixing some language concepts here...
A reference is like a pointer no?
No.
A reference is a "nickname" of an object. No more, no less.
Okay, in fact it is implemented as a pointer with special rules but it's not true in every use: the compiler is free to implement it in whatever way it want.
In case of a function attribute, it's often implemented as a pointer. But you don't have to even know about it.
For you, it's just the nickname of an object.
If we were to replace the reference
with a pointer the compiler complains.
Why is the reference different to a
pointer in this way, what's going on
behind the scenes?
I guess your first error did make things fuzzy for you?
You're not passing it "a statically allocated variable of type SomeClass", you're passing it a reference to a SomeClass object you created on the stack in main().
Your function
void doSomething(SomeClass& ref)
Causes a reference to a in main to be passed in. That's what & after the type in the parameter list does.
If you left out the &, then SomeClass's (a's) copy constructor would be called, and your function would get a new, local copy of the a object in main(); in that case anything you did to ref in the function wouldn't be seen back in main()
Perhaps your confusion arises from the fact that if you have two functions:
void doThingA(int a) {
a=23;
}
void doThingB(int &a) {
a=23;
}
The calls to them look the same, but are in fact very different:
int a=10;
doThingA(a);
doThingB(a);
The first case, doThingA(int), creates a completely new variable with the value 10, assignes 23 to it and returns. The original variable in the caller remains unchanged. In the second case, doThingB(int&), where the variable is passed by reference, a new variable is create with the same address as the variable passed in. This is what people mean when they say passing by reference is like passing by pointer. Because both variables share the same address (occupy the memory location) when doThingB(int&) changes the value passed in, the variable in the caller is also changed.
I like to think of it as passing pointer without all that annoying pointer syntax. Having said that though, I find functions that modify variables passed by reference to be confusing, and I almost never do it. I would either pass by const reference
void doThingB(const int &a);
or, if I want to modify the value, explicitly pass a pointer.
void doThingB(int *a);
Reference is not a pointer. You simply pass parameters as "by value" and use-it . Under the hood only a pointer will be used, but this is just under the hood.
A reference is nothing at all like a pointer, it is an alias - a new name - for some other object. That is one reason for having both!
Consider this:
Someclass a;
Someclass& b = a;
Someclass& c = a;
Here we first create an object a, and then we say that b and c are other names for the same object. Nothing new is created, just two additional names.
When b or c is a parameter to a function, the alias for a is made available inside the function, and you can use it to refer to the actual object.
It is that simple! You don't have to jump through any loops with &, *, or -> like when using pointers.
Though the question has been already answered adequately, I can't resist sharing few more words on the related language feature of "References in C++".
As C programmers, we have two options available when passing variables to functions:
Pass the value of the variable (creating a new copy)
Pass the pointer to the variable.
When it comes to C++, we are usually dealing with objects. Copying such objects on each function call that needs to work on that object is not recommended due to space (and also speed) considerations. There are benefits involved with passing the variable address (via the pointer approach), and though we can make the pointer 'const' to avoid any changes through the pointer, the syntax with pointers is rather clumsy (miss the dereference operator at a place or two and end up spending hours debugging!).
C++, in providing 'references', packages the best of both options:
The reference can be understood to be as good as passing the address
The syntax to use the reference is the same as working on the variable itself.
The reference would always point to 'something'. Hence no 'null-pointer' exceptions.
Additionally, if we make the reference 'const', we disallow any changes to the original variable.

Any Default Pass By Reference DataTypes in C++?

I understand that unlike C# ( where class is passed by reference and struct is passed by default), both structure and class in C++ are passed by value into a method, unless it is explicitly modified to pass by reference.
i.e.,
// this is a method that passes by reference
void PassReferenceOp(MyClass &myclass, MyStruct &myStruct)
{
}
// this is a method that passes by value
void PassReferenceOp(MyClass myclass, MyStruct myStruct)
{
}
My question is, is it that there is no data structure, data types in C++ that passes into a method by reference? That no matter I am using std::list, std::list::iterator,std::map, or any data types I create, be it struct or class, all are pass by reference?
There are no default pass by reference types. Of course, there are references which are passed by value (most notably, smart pointers), the difference between which you could argue for a while.
Not that I see the importance. Adding an & is hardly the epitome of difficulty or time wastage.
The closest to what you want is not pass-by-reference but using pointers.
References both in Java and C# are more closely related to pointers than to C++ references: A reference in C++ is an alias to the object, equivalent to the ref keyword in C#, while a reference in C#/Java is an entity that refers (points) to the real instance (as a pointer in C/C++).
The following two are equivalent (assuming a struct type in C#):
void foo( type& param ); // c++
void foo( ref type param ); // c#
Now for reference types, the equivalent would be:
void foo( type* param ); // c++
void foo( type param ); // c#
With the difference that pointers in c++ are not automatically dereferenced, that is you have to use operator-> instead of . to access members.
C++ has different argument passing and assignment semantics. Whether something is passed by value, by reference, or by pointer, is not determined by its type. Argument passing and assignment is always explicit.
Nope, no such type exists.
And (part of) the reason for this is that it just wouldn't make sense in C++. In C++, it makes a big difference whether an object is passed by value or reference, so the function needs to know how its parameter is passed.
In your code snippet, when implementing the first function, we know that we are given two references when the function is called: so any modification we make to these objects will be visible to the caller.
In the second function, we know that we are given two objects by value, meaning we can modify them freely, and that their destructors will be called at the end of the function.
If there was a sneaky type that broke this guarantee, and turned out to be a reference anyway, we could make our code blow up in all sorts of new and exciting ways.
Take a simple template function like this:
template <typename T>
T make_default() { return T(); }
If T is such a hypothetical "reference type", then this would be undefined behavior: it would create a local instance, and then return a reference to it. A reference to the object that just went out of scope and was deleted when the function returned.
Such reference types just don't really work well unless you have a garbage collector and throw away deterministic destruction, which is a pretty major C++ feature.
In C++, ownership is important. In order to write correct code, I need to know who owns every object. When is it created, when is it destroyed? A reference doesn't keep the object it points to alive, so if you're not careful, it can end up pointing to an object that no longer exists, as in my little template example above. We need to know whether or not the object we're working with is a reference.
By default, all C++ parameters are passed by value. Use & to indicate a reference.

Operator & and * at function prototype in class

I'm having a problem with a class like this:
class Sprite {
...
bool checkCollision(Sprite &spr);
...
};
So, if I have that class, I can do this:
ball.checkCollision(bar1);
But if I change the class to this:
class Sprite {
...
bool checkCollision(Sprite* spr);
...
};
I have to do this:
ball.checkCollision(&bar1);
So, what's the difference?? It's better a way instead other?
Thank you.
In both cases you are actually passing the address of bar1 (and you're not copying the value), since both pointers (Sprite *) and references (Sprite &) have reference semantics, in the first case explicit (you have to explicitly dereference the pointer to manipulate the pointed object, and you have to explicitly pass the address of the object to a pointer parameter), in the second case implicit (when you manipulate a reference it's as if you're manipulating the object itself, so they have value syntax, and the caller's code doesn't explicitly pass a pointer using the & operator).
So, the big difference between pointers and references is on what you can do on the pointer/reference variable: pointer variables themselves can be modified, so they may be changed to point to something else, can be NULLed, incremented, decremented, etc, so there's a strong separation between activities on the pointer (that you access directly with the variable name) and on the object that it points to (that you access with the * operator - or, if you want to access to the members, with the -> shortcut).
References, instead, aim to be just an alias to the object they point to, and do not allow changes to the reference itself: you initialize them with the object they refer to, and then they act as if they were such object for their whole life.
In general, in C++ references are preferred over pointers, for the motivations I said and for some other that you can find in the appropriate section of C++ FAQ.
In terms of performance, they should be the same, because a reference is actually a pointer in disguise; still, there may be some corner case in which the compiler may optimize more when the code uses a reference instead of a pointer, because references are guaranteed not to change the address they hide (i.e., from the beginning to the end of their life they always point to the same object), so in some strange case you may gain something in performance using references, but, again, the point of using references is about good programming style and readability, not performance.
A reference cannot be null. A pointer can.
If you don't want to allow passing null pointers into your function then use a reference.
With the pointer you need to specifically let the compiler know you want to pass the address of the object, with a reference, the compiler already knows you want the ptr. Both are ok, it's a matter of taste, I personally don't like references because I like to see whats going on but thats just me.
They both do the (essentially) same thing - they pass an object to a function by reference so that only the address of the object is copied. This is efficient and means the function can change the object.
In the simple case you give they are equivalent.
Main differences are that the reference cannot be null, so you don't have to test for null in the function - but you also cannot pass a null object if the case of no object is valid.
Some people also dislike the pass by reference version because it is not obvious in the calling code that the object you pass in might be modified. Some coding standards recommend you only pass const references to functions.