13

What is the difference? Because this:

int Value = 50;
int *pValue = &Value;

*pValue = 88;

and ref version do the same:

int Value = 50;
int &rValue = Value;

rValue = 88;

Which one is better to use? Thanks.

Quest
  • 2,764
  • 1
  • 22
  • 44
  • It's noteworthy that references are often used as parameters to functions. (The snippet above makes little sense if it is in the same scope -- why declare an alias if the actual variable is readily at hand?) Reference arameters to functions which change that value can be confusing because the caller can not tell whether it's a reference or not without looking at the function signature. It's perhaps more important to discuss pointer vs. reference in that scenario. – Peter - Reinstate Monica Jan 11 '15 at 15:53

6 Answers6

20

In this case, they are equivalent.

It does not matter which you use, and neither is "best".

If you really want to choose between them then the reference is probably more idiomatic. I generally stick to references wherever I can because my OCD likes it: they feel "tighter", cannot be re-bound (with or without you noticing) and don't require a dereference to get to the value.

But I'm not aware of any general consensus on the issue for cases such as this.

Also note that the two may not compile to the same code if your implementation does not implement references with pointers, though I know of no implementation like that, and you wouldn't notice the difference anyway.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    @Quest: There are others, but there are also cases where using a pointer is valid and using a reference is not, such as if you attempted to re-bind the handle to a different `int`, or if you wanted to hold a "null" handle, or etc etc. I try not to make generalisations when people ask about pointers vs references. – Lightness Races in Orbit Feb 19 '14 at 15:27
  • @LightnessRacesinOrbit Also, I believe that **reference is tied to the type.** We can have a pointer of type `void*` which is generic, while I know of no scenario where reference is generic – SimpleGuy Aug 16 '16 at 14:23
  • @SimpleGuy: Indeed; [C++ prohibits that](http://coliru.stacked-crooked.com/a/21369499a0fdac49). There's no "interface" that can be exposed by the reference, and since that happens transparently (i.e. without a derefernce), it would be kind of weird to allow it. Still, theoretically it could be allowed just as a `void*` is - you'd have to cast it to something else before "using" it. – Lightness Races in Orbit Aug 16 '16 at 15:55
20

A pointer is the address of the memory location. You can change the value of that address to point at different memory addresses.

A reference is an alias of the variable. You can only assign this alias during declaration. You cannot change which variable the reference is an alias of after it's declared.


The following pointer assignments are not possible with references.

int a = 10;
int b = 20;

int* pInt = NULL; // A pointer pointing at nothing.
pInt = &a; // pInt now points at a
pInt = &b; // pInt now points at b

As for which one is better, it all depends on context.

I use references for method and function parameters.

void updateFoo(Foo& foo)

I use references to alias complex objects.

Foo& foo = bar.getBaz().getFoo(); // easy access to foo

I use pointers for dynamically allocated objects.

Foo* pFoo = new Foo();

I use pointers for things which may point at different values (including no value at all).

Foo* pFoo = NULL;

if (condition1)
    pFoo = &foo1;
else (condition2)
    pFoo = &foo2;

As a general rule, I default to references and use pointers in places where the limitations on references cause problems.

Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
  • Since the question is about pointers versus references, then I assume this only means function parameters, and a pointer parameter is a copy of the pointer, so the function can't change the actual pointer. The parameter would have to be a pointer to a pointer in order to change the original pointer. One issue with references is that that there's no way to know if a parameter is being passed by value or by reference when looking at the calling code; this can only be done by looking at a function prototype or the function itself which may be in another source file. – rcgldr Feb 19 '14 at 19:13
  • Also, a bit on a tangent here but it seems to me your proposed use of using references to alias complex objects is a bit of an abuse since you're essentially violating Law of Demeter and that signals a problem in OO design. Saying that, I am not a C(++) programmer and that practice may be (more) acceptable than in other languages for some reason. – quantum Mar 23 '14 at 21:34
11

The differences are:

Reference is an alias of an object and has the same address as the object.

int a;         //  address of   a : 0x0012AB
int &ref = a;  //  address of ref : 0x0012AB (the same)

References must be initialized :

int &ref = a; // GOOD, is compiling
int &ref;     // BAd, is not compiling

Pointer is another variable that holds an address:

int a = 5;     //  address of a : 0x0012AB 
int *p = &a;   //  address of p : 0x0012AF (is different )

// value of a is 5
// value of p is 0x0012AB  (address of a)

Pointers can be NULL

int *p = NULL;
Dorin
  • 1,016
  • 1
  • 11
  • 15
3

My rule of thumb is to favor using a reference or const reference, unless a pointer is required.

The reference may not be reseated, and it is syntactically cleaner. The reference also guarantees to you that the reference is not NULL.

I may also use a pointer for convenience when using arrays.

justin
  • 104,054
  • 14
  • 179
  • 226
  • The reference itself makes no "guarantee", really. You won't have a "null reference" in a well-defined program, but that's more down to the programmer than the reference feature. – Lightness Races in Orbit Feb 19 '14 at 15:29
  • Is there a (non-hack) example where a reference points to an invalid variable? Sounds interesting how something like that could be achieved – MatthiasB Feb 19 '14 at 15:31
  • @LightnessRacesinOrbit that's why i wrote "to you". if you have been passed a null reference, UB's already happened. – justin Feb 19 '14 at 15:32
  • @MatthiasBonora perhaps you are looking for a case where the referenced goes out of scope or is destroyed before the reference. this can happen if a container (e.g. vector) reallocates its storage during resize. – justin Feb 19 '14 at 15:36
1

I agree with justin's answer and would like to clarify it with the tiniest example.

Suppose you don't quite remember the syntax of a 2D image geometric library: is it

bool BooleanOr( const Bitmap & input1, const Bitmap & input2, Bitmap * output );

or is it

bool BooleanOr( Bitmap * output, const Bitmap & input1, const Bitmap & input2 );

If in your company everybody uses pointers for outputs and const references for inputs it's virtually impossible to make a mistake: when you see calls such as

BooleanOr( thisBitmap, thatBitmap, & anotherBitmap );

you immediately know the syntax.

Michael
  • 5,775
  • 2
  • 34
  • 53
1

Great answers here. I would like to point out 2 specific usages of references:-

Case 1: While implementing operator[]. This operator typically needs to return something that can be used as the target of an assignment Example:-

vector<int> v(20);
v[1] = 5; //The target of the assignment is the return value of operator []

Here the operator [] returns a reference of the element at the specified index in the vector. Had operator [] been designed to return a pointer to the element at the specified index the 2nd line would have to be written like this:-

*v[1] = 5

Now that makes v look like it's a vector of pointers - which it's definitely not!! Thus for sanity to prevail - the operator [] returns a reference and not a pointer to the indexed element in the vector

Case 2: No explicit null check required for references. Some answers have already talked about it - wanted to present the advantage using a code snippet:-

void fun(const int& val)
{
  cout << val;
}

void fun(const int* val)
{
  if (val){ //Additional overhead with pointers
    cout << *val;
  }
}
Zakir
  • 2,222
  • 21
  • 31