views:

30105

answers:

19

I know references are syntactic sugar, so easier code to read and write :)

But what are the differences?

Summary from answers and links below:

  1. A pointer can be re-assigned any number of times while a reference can not be reassigned after initialization.
  2. A pointer can point to NULL while reference can never point to NULL
  3. You can't take the address of a reference like you can with pointers
  4. There's no "reference arithmetics" (but you can take the address of an object pointed by a reference and do pointer arithmetics on it as in &obj + 5).

To clarify a misconception:

The C++ standard is very careful to avoid dictating how a compiler must implement references, but every C++ compiler implements references as pointers. That is, a declaration such as:

int &ri = i;

allocates the same amount of storage as a pointer, and places the address of i into that storage.

So pointer and reference occupies same amount of memory

As a general rule,

  • Use references in function parameters and return types to define attractive interfaces.
  • Use pointers to implement algorithms and data structures.

Interesting read:

+2  A: 

Apart from syntactic sugar, a reference is a const pointer (not pointer to const thing, a const pointer). You must establish what it refers to when you declare the reference variable, an you cannot change it later.

Arkadiy
I'm not sure that calling a reference a "const pointer" is helpful. The _only_ way in which a reference is like a pointer is that it can be made to refer to some pre-existing memory location. A reference shares no other characteristics of a pointer.
Chris Ammerman
@Turbulent Intellect: a C++ reference can be thought of as a constant pointer with automatic indirection - see my answer...
Christoph
@Christoph: Except that reference parameters in functions that are inlined can actually behave as a "shadow" of the parent variable (even staying within a register) whereas the a pointer (even with automatic indirection) that is dereferenced will result in memory accesses.
Adisak
+59  A: 

1) A pointer can be re-assigned:

int x = 5;
int y = 6;
int *p;
p =  &x;
p = &y;
*p = 10;
assert(x == 5);
assert(y == 10);

A reference cannot, and must be assigned at initialization:

int x = 5;
int y = 6;
int &r = x;

2) A pointer has its own memory address and size on the stack (4 bytes on x86), whereas a reference shares the same memory address but also takes up some space on the stack. Since a reference has the same address as the original variable itself, it is safe to think of a reference as another name for the same variable. Note: What a pointer points to can be on the stack or heap. Ditto a reference. My claim in this statement is not that a pointer must point to the stack. A pointer is just a variable that holds a memory address. This variable is on the stack. Since a reference has its own space on the stack, and since the address is the same as the variable it references. More on stack vs heap. This implies that there is real a address of a reference that the compiler will not tell you.

int x = 0;
int &r = x;
int *p = &x;
int *p2 = &r;
assert(p == p2);

3) you can have pointers to pointers to pointers offering extra levels of indirection. Whereas references only offer 1 level of indirection.

int x = 0;
int y = 0;
int *p = &x;
int *q = &y;
int **pp = &p;
pp = &q;//*pp = q
**pp = 4;
assert(y == 4);
assert(x == 0);

4) Pointer can be assigned NULL directly, whereas reference cannot. If you try hard enough, and you know how, you can make the address of a reference NULL. Likewise, if you try hard enough you can have a reference to a pointer, and then that reference can contain NULL.

int *p = NULL;
int &r = NULL; <--- compiling error

5) Pointers can iterate over an array, you can use ++ to go to the next item that a pointer is pointing to, and + 4 to go to the 5th element. This is no matter what size the object is that the pointer points to.

6) A pointer needs to be dereferenced with * to access the memory location it points to, whereas a reference can be used directly. A pointer to a class/struct uses -> to access it's members whereas a reference uses a .

7) A pointer is a variable that holds a memory address. Regardless of how a reference is implemented, a reference has the same memory address the item it references.

8) References cannot be stuffed into an array, whereas pointers can be (Mentioned by user @litb)

Brian R. Bondy
Reference can be null. In some cases, you pass refrence params in as this: function(*ptr);If ptr is NULL, so will be the reference.
Arkadiy
Pat Notz
IN VC++ *ptr will crash, pretty sure in gc++ it will segfault too
Brian R. Bondy
I think point 2 is incorrect. See this example program:http://pastebin.com/f5252f8a8This implies that on gcc on my machine, the reference is implemented with a pointer.Output:Size of class: 8Value of ref before hack: 1Value of ref after hack: 2Value of ref after hack, with y changed: 3
Nick
Number 2 is *not* true. A references is not simply "another name for the same variable." References may be passed to functions, stored in classes, etc. in a manner very similar to pointers. They exist independently from the variables they point to.
Derek Park
Also this: "A pointer has its own memory address and size on the stack". Pointers need not be allocated on the stack (and most of them are generally not.)
Derek Park
Derek a pointer is a variable just like any other one. On an x86 system it is 4 bytes. These 4 bytes are on the stack. I didn't claim what they point to are on the stack.
Brian R. Bondy
I don't think it is good and safe to think that, because it's wrong :-pI'd be inclined to remove point 2 from an otherwise good answer.
Nick
Brian, referring to point 2, do you know of any compiler that actually does this? It is implementation-dependent, but references are typically implemented with pointers.
Derek Park
how the internal structure of a reference is implemented doesn't matter. What matters is that the address of the reference is the same as the address of the variable itself. Therefore they can be used interchangeably.
Brian R. Bondy
Nick you could use the same argument as your link to say that pointers are implemented as pointers to pointers but you didn't mention it. int x = 0; int y = 0; int *p = *(int**)(Because it doesn't matter.
Brian R. Bondy
I verified by the way that a reference does take up some space on the stack, I modified my #3 to include this info. The address of operator though still does specify the same as the variable that it refers to.
Brian R. Bondy
Brian, the stack is not relevant. References and pointers do not have to take space on the stack. They can both be allocated on the heap.
Derek Park
Derek please see my previous post, I don't think you read it or you didn't read it carefully enough..."Derek a pointer is a variable just like any other one. On an x86 system it is 4 bytes. These 4 bytes are on the stack. I didn't claim what they point to are on the stack"
Brian R. Bondy
Brian, the fact that a variable (in this case a pointer or reference) requires space does *not* mean it requires space on the stack. Pointers and references may not only *point* to the heap, they may actually be *allocated* on the heap.
Derek Park
agree, but i'm just trying to get the point across that in this situation: int x = 0; int *p = , the p takes up 4 bytes on the stack. I know it is possible to say (new int*) to allocate the pointer itself on the heap.
Brian R. Bondy
you an modify if you'd like to be more explicit there, but I think its not really needed.
Brian R. Bondy
another important diff: references cannot be stuffed into an array
Johannes Schaub - litb
Derek, there is no mention in the standard that a reference requires space. regardless what you do with a reference, even if you take its address, there can be no additional space involved and a reference can just be a "real" alias for the other object it references.
Johannes Schaub - litb
good suggestion about the array, I added it.
Brian R. Bondy
@litb: While the standard might not require space allocated for the reference, in many cases the compiler will be forced to reserve space. Consider a reference within a class, surely each instance of the class can refer to different external objects, and to which object they refer must be held somehow --in most implementations as an automatically dereferenced pointer (I cannot really think of any other possible implementation that fits all use cases, but then again, I am no expert)
David Rodríguez - dribeas
+6  A: 

Another benefit, is that a reference can never be NULL. No more exhaustive parameter checking :-).

A: 

@axs6791 I'm not sure what you mean exactly. References can be assigned to a derived class:

class A
{
};

class B : public A
{
};

void foo()
{
    B b;

    A& a = b;
}

What case can you do with pointers that wouldn't work with references?

Rob Walker
+2  A: 

A very simple answer is that the only really significant things that a reference has in common with a pointer are:

  1. A reference can be made to refer to a pre-existing memory location, which a normal variable cannot.
  2. A reference can be of a type that is a parent or child class of the original variable's type.

Otherwise, a reference basically acts like the original variable. It is effectively an alias to the original variable.

Chris Ammerman
"It is effectively an alias to the original variable." - I wouldn't go so far - in most cases, using references will have the same performance hit as using pointers: the indirection still has to happen!
Christoph
Certainly, but I'd question how often this performance difference is really relevant except in the most performance-intensive applications or efficiency-sensitive platforms. Unless your code is already highly tuned, pointers/references aren't likely to be your bottleneck.
Chris Ammerman
+9  A: 

Contrary to popular opinion, it is possible to have a reference that is NULL.

int * p = NULL;
int & r = *p;
r = 1;  // crash! (if you're lucky)

Granted, it is much harder to do with a reference - but if you manage it, you'll tear your hair out trying to find it.

Edit: a few clarifications.

Technically, this is an invalid reference, not a null reference. C++ doesn't support null references as a concept, as you might find in other languages. There are other kinds of invalid references as well.

The actual error is in the dereferencing of the NULL pointer, prior to the assignment to a reference. But I'm not aware of any compilers that will generate any errors on that condition - the error propagates to a point further along in the code. That's what makes this problem so insidious. Most of the time, if you dereference a NULL pointer, you crash right at that spot and it doesn't take much debugging to figure it out.

My example above is short and contrived. Here's a more real-world example.

class MyClass
{
    ...
    virtual void DoSomething(int,int,int,int,int);
};

void Foo(const MyClass & bar)
{
    ...
    bar.DoSomething(a,Long,list,of,parameters);  // crash occurs here - obvious why?
}

MyClass * GetInstance()
{
    if (somecondition)
        return NULL;
    ...
}

MyClass * p = GetInstance();
Foo(*p);
Mark Ransom
As a nitpick, I'd say that the reference isn't actually null - it references bad memory.Although it is a valid point that just because it's a reference, doesn't mean that it refers to something that's valid
Nick
The code in question contains undefined behavior. Technically, you cannot do anything with a null pointer except set it, and compare it. Once your program invokes undefined behavior, it can do anything, including appearing to work correctly until you are giving a demo to the big boss.
KeithB
I didn't test it but I think the code above just crash at the second line while dereferencing the NULL pointer.
Vincent Robert
@Vincent: In fact, no, sometimes, the second line is silently invoked (remember compilers can implement references as pointers, so...)... So the crash happens when you us the reference.
paercebal
Anyway, the coder dereferenced a pointer without testing it. This is the source of the error. At that point, or sometimes after, the program will crash. This can happen everytime a pointer is converted to a reference. It means that you can reduce the risk by removing as much pointers as possible...
paercebal
mark has a valid argument. the argument that a pointer could be NULL and you therefor have to check is not real either: if you say a function requires non-NULL, then the caller has to do that. so if the caller doesn't he is invoking undefined behavior. just like mark did with the bad reference
Johannes Schaub - litb
Depending on the implementation, hardware and OS, the act of setting a reference variable to an invalid address can an exception. The address 0 may or may not be valid, again depending on hardware and OS.
Pete Kirkham
+7  A: 

If you want to be really pedantic, there is one thing you can do with a reference that you can't do with a pointer: extend the lifetime of a temporary object. In C++ if you bind a const reference to a temporary object, the lifetime of that object becomes the lifetime of the reference.

std::string s1 = "123";
std::string s2 = "456";

std::string s3_copy = s1 + s2;
const std::string& s3_reference = s1 + s2;

In this example s3_copy copies the temporary object that is a result of the concatenation. Whereas s3_reference in essence becomes the temporary object. It's really a reference to a temporary object that now has the same lifetime as the reference.

If you try this without the const it should fail to compile. You cannot bind a non-const reference to a temporary object, nor can you take its address for that matter.

Matt Price
but whats the use case for this ?
digitalSurgeon
Well, s3_copy will create a temporary and then copy construct it into s3_copy whereas s3_reference directly uses the temporary. Then to be really pedantic you need to look at the Return Value Optimization whereby the compiler is allowed to elide the copy construction in the first case.
Matt Price
David Rodríguez - dribeas
@digitalSurgeaon: in some cases this behavior is very handy. I use it for instance to create anonymous temporary objects created on-the-fly when they are passed as parameters. You can also do it with pointers using new but then objects are created in the heap not on the stack, and you should be extra cautious not to forget to delete it.
kriss
+3  A: 

You forgot the most important part

member-access with pointers uses ->
member-access with references uses .

foo.bar is clearly superior to foo->bar in the same way that vi is clearly superior to emacs :-)

Orion Edwards
here we go..... :P
matpalm
+1 for dispelling the common myth that the editor war has not ended with one clear winner
kizzx2
A: 

@Brian: References can take up memory, just as pointers do.

For example, if you have a member variable of a class which is a reference, then every instance of the class will have memory allocated for that reference.

In some cases, a compiler can optimize away the need to allocate memory for a reference; and there's no nice way to get the address of a reference in your code (&my_reference just returns the address of the referred-to object). In those aspects I agree that references act as if they don't take up memory - but they can.

Tyler
A: 

@Orion Edwards

member-access with pointers uses ->

member-access with references uses .

This is not 100% true. You can have a reference to a pointer. In this case you would access members of de-referenced pointer using ->

struct Node { Node *next; };

Node *first;

// p is a reference to a pointer
void foo(Node*&p) {
  p->next = first;
}

Node *bar = new Node;
foo(bar);

--

OP: Are you familiar with the concepts of rvalues and lvalues?

Kapil Kapre
A: 

I use references unless I need either of these:

  • Null Pointers can be used as a sentinel value, often a cheap way to avoid function overloading or use of a bool.

  • You can do arithmetic on a pointer. For example, p += offset;

Aardvark
A: 

Another interesting use of references is to supply a default argument of a user-defined type:

class UDT
{
public:
   UDT() : val_d(33) {};
   UDT(int val) : val_d(val) {};
   virtual ~UDT() {};
private:
   int val_d;
};

class UDT_Derived : public UDT
{
public:
   UDT_Derived() : UDT() {};
   virtual ~UDT_Derived() {};
};

class Behavior
{
public:
   Behavior(
      const UDT &udt = UDT()
   )  {};
};

int main()
{
   Behavior b; // take default

   UDT u(88);
   Behavior c(u);

   UDT_Derived ud;
   Behavior d(ud);

   return 1;
}

The default flavor uses the 'bind const reference to a temporary' aspect of references.

Don Wakefield
+2  A: 

A reference on the stack doesn't take up any space at all. Or rather, it doesn't matter how much space it takes up since you can't actually see any side effect of whatever space it would take up.

On the other hand, one major difference between references and pointers is that temporaries assigned to const references live until the const reference goes out of scope.

For example:

class scope_test
{
public:
    ~scope_test() { printf("scope_test done!\n"); }
};

...

{
    const scope_test &test= scope_test();
    printf("in scope\n");
}

will print:

in scope
scope_test done!

This is the language mechanism that allows ScopeGuard to work.

MSN

MSN
+2  A: 

Actually, a reference is not really like a pointer.

A compiler keeps "references" to variables, associating a name with a memory address, that's its job to translate any variable name to a memory address when compiling.

When you create a reference, you only tell the compiler that you assign another name to the pointer variable, that's why references cannot "point to null", because a variable cannot be, and not be.

Pointers are variables, they contain the address of some other variable, or can be null. The important thing is that a pointer has a value, while a reference only has a variable that it is referencing.

Now some explanation of real code:

int a = 0;
int& b = a;

Here you are not creating another variable that points to a, you are just adding another name to the memory content holding the value of a. This memory now has two name, a and b, and can be addressed using either name.

void increment(int& n)
{
    n = n + 1;
}

int a;
increment(a);

When calling a function, the compiler usually generates memory spaces for the arguments to be copied to. The function signature defines the spaces that should be created and gives the name that should be used for these spaces. Declaring a parameter as a reference just tells the compiler to use the input variable memory space instead of allocating a new memory space during the method call. It may seem strange to say that your function will be directly manipulating a variable declared in the calling scope but remember that when executing a compiled code, there is no more scope, there is just plain flat memory and your function code could manipulate any variables.

Now there may be some cases where your compiler may not be able to know the reference when compiling, like when using an extern variable. So a reference may or may not be implemented as a pointer in the underlying code. But in the examples I gave you, it will most likely not be implemented with a pointer.

Vincent Robert
A reference is a reference to l-value, not necessarily to a variable. Because of that, it's much closer to a pointer than to a real alias (a compile-time construct). Examples of expressions that can be referenced are *p or even *p++
Arkadiy
Right, I was just pointing the fact that a reference may not always push a new variable on the stack the way a new pointer will.
Vincent Robert
+2  A: 

What's a C++ reference (for C programmers):

A reference can be thought of as a constant pointer (not a pointer to a constant value!) with automatic indirection - ie the compiler will apply the * operator for you.

All references must be initialized with a non-null value or compilation will fail. It's neither possible to get the address of a reference - the address operator will return the address of the referenced value instead - nor is it possible to do arithmetics on references.

C programmers might dislike C++ references, as it will no longer be obvious when indirection happens or if an argument gets passed by value or by pointer.

C++ programmers might dislike using pointers, as they are considered 'unsafe' - although references aren't really any safer than constant pointers - and lack the convenience of automatic indirection.

Consider the following statement from the 'C++ FAQ Lite':

"Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object. It is not a pointer to the object, nor a copy of the object. It is the object."

That's how some people want you to think about references. But if a reference really were the object, how could there be dangling references? In unmanaged languages, it's impossible for references to be any 'safer' than pointers - there just is no way to alias values across scope boundaries!

Coming from a C background, C++ references may look like a somewhat braindead concept, but one should still use them instead of pointers if possible - when in Rome...

Christoph
@Christoph: well references can be dangling only if you got it somewhere through dereferencing some pointer.
kriss
A: 

Also, a reference that is a parameter to a function that is inlined may be handled differently than a pointer.

void increment(int *ptrint) { (*ptrint)++; }
void increment(int &refint) { refint++; }
void incptrtest()
{
    int testptr=0;
    increment(&testptr);
}
void increftest()
{
    int testref=0;
    increment(testref);
}

Many compilers when inlining the pointer version one will actually force a write to memory (we are taking the address explicitly). However, they will leave the reference in a register which is more optimal.

Of course, for functions that are not inlined the pointer and reference generate the same code and it's always better to pass intrinsics by value than by reference if they are not modified and returned by the function.

Adisak
A: 

Another difference is that you can have pointers to a void type (and it means pointer to anything) but references to void are forbidden.

int a;
void * p = &a; // ok
void & p = a;  //  forbidden

I can't say I'm really happy with this particular difference. I would much prefer it would be allowed with the meaning reference to anything with an address and otherwise the same behavior for references.

kriss
A: 

Here is a video tutorial that explains difference between lvalue and rvalue expressions - terms crucial for good understanding of references and pointers too): C++ Tutorial (10) on YT

mloskot
A: 

Generally, I dont see nothing extremal positive in conception of references. Simple but powerful rule of programming tells: Nothing artificial, simple things are preferrable! So, if there is nothing positive against pointers, why we need references?? Remember, how Java creators rejected rederences and pointers.

Sceptic