views:

307

answers:

9

Possible Duplicate:
Difference between pointer variable and reference variable in C++

I am reading about the book "Inside the C++ Object Model" by Stanley Lippman. What puzzles me is the difference between a "reference" of an object and a "pointer" to an object. I know that a reference must be initialized when declared, while a pointer could be left for later initialization. But I want to know the physical implementation difference between them.

Why should there be the "reference" mechanism; isn't it overlapping the function of a pointer? Under what circumstance should we use reference other than pointer? Many thanks.

+1  A: 

References are in most cases internally pointers (especially when stored or passed to functions). They operate the same way as a pointer would, as long as only operations valid for both are used.

The extra checks and syntactic sugar for references is strictly a compile-time feature, much like the type system (most information about data types is lost during compilation).

The important differences are

  • Reference always points to an object (cannot be NULL)
  • Reference points to one object only (not to an array like a pointer might)
  • Reference must be initialized initially (otherwise you get a compile error)
  • Reference cannot be modified after initialization to point somewhere else
  • Deletion of the object pointed to by a reference, while the reference variable stays alive, is Undefined Behavior (but not a compile error)
Tronic
+1. Expanded UB to Undefined Behavior though.
Billy ONeal
Thanks, Tronic. I learned from you answer that "reference and type systems are compile-time features".
smwikipedia
A: 

References are just good for you as a C++ programmer. The compiler implements references as pointers anyway so it doesn't care if you use a pointer or a reference.

References is, like you said, better than pointers in many cases because they protect the callee from bad input (bad pointers often results in seg faults) and you can also set them to const, which provides better protection from changes than setting a pointer to const.

monoceres
...seems to be yet another syntax sugar. Thanks, monoceres. :D
smwikipedia
A: 

C++ references are largely a syntactic mechanism.

Consider

int x;
int &y = x;
int *z = &x;

The expression (*z) is the same thing as (y).

Aside from saving you typing a few characters, the only language thing going on here is that as reference cannot be null.

bmargulies
-1 not true, the c++ standards do not dictate how references are implemented (though this is usually how it is implemented). Also, you could hack a reference so that it shows up as null e.g. "int " (but doing so is extremely poor coding).
Grant Peters
@Grant Peters: I didn't how they are implemented, I said how they effectively work.
bmargulies
@bmargulies: yeah, I guess you didn't. I must have been reading too much into it previously (probably from reading so many different answers), I would retract my -1, but SO doesn't seem to think that our opinions can change (only if the answer changes can we change our vote on it)
Grant Peters
@Grant Peters: no problem.
bmargulies
+6  A: 

A reference can be thought of as an implicitly de-referenced constant pointer (note this). Once a reference, always a reference. It allows for ease of writing code. Unless of course, you bring in move semantics and r-value references. The standard doesn't mandate how references should be implemented just as it does not mandate how pointers should be implemented. Most of the time though, pointers are synonymous with addresses of objects.

dirkgently
+10  A: 

Most references are implemented using a pointer variable i.e. a reference usually takes up one word of memory. However, a reference that is used purely locally can - and often is - eliminated by the optimizer. For example:

  struct S { int a, int b[100]; };  
  void do_something(const vector<S>& v)
  {
    for (int i=0; i<v.size(); ++i) {
        int*& p = v[i].b;
          for (int j=0; j<100; ++j) cout <<p[j];
  }

In this case, p needs not be stored in memory (maybe it just exists in a register, maybe it disappears into the instructions).

Prasoon Saurav
Prasoon, you've a repetition up there, I guess you need to remove the "are implements" in your answer. Also "that it" should be changed to "that is"
legends2k
@legends2k : Thanks! Done.
Prasoon Saurav
+4  A: 

Use references when you can, and pointers when you need to. Reasons you'd need to use a pointer:

  1. There might not be an object for it to point at (null pointer, no null references).
  2. You might need to refer to different objects during its lifetime.
  3. You might need to refer to a whole array of objects (but std::vector is usually better).
Jerry Coffin
A: 

Hi

One example where reference ought to be used instead of pointers:

enum day
{
    Mon, Tue, Wed, Thu, Fri, Sat, Sun
};

day d;

day *operator++(day *d);

The operator ++ can be invoked using ++&d, which does not look that intuitive.

One big catch here is that all overloaded operator functions must either be a member of a class, or have a parameter of type T, T &, or T const &, where T is a class or enumeration type. So, in this case day *operator++(day *d); won't even compile.

It works fine using reference i.e.

day &operator++(day &d);

which can be invoked simply as ++d;

Here is a nice article from where I got this example.

cheers

Andriyev
you can't overload operators on built-in types like pointers
Ben Voigt
Well, that is why it can not be implemented. My answer includes that part.
Andriyev
+2  A: 

A pointer is a distinct value, independent of the data it points to. (The number 0x12345678 is meaningful as a pointer value even if there's no meaningful data at address 0x12345678 in memory.) Because it's a distinct value, it can be manipulated on its own: you can increment or decrement it, compare it against other pointers, and print its value to the screen, regardless of whether it actually "points to anything."

You can't do any of those things with a reference because it's not a distinct value. It's an alias, an alternate name (possibly in a different scope) for some existing value. This makes references easier to use (since they act just like the object they refer to, no dereferencing needed), and also safer (since, if used properly, they always refer to an object; there's no such thing as a dangling or null reference).

It may be true that references typically get translated into pointers in the compiled machine code, but you should think of that as a private implementation detail of the compiler, not a guarantee. References are their own concept with their own use-cases, not just a different way of working with pointers.

When you need a distinct pointer-like value that you can manipulate and examine independently of the data it points to, use a pointer (or, preferably, a smart-pointer class). When you just need a way to take a value that exists in one scope and make it available in another scope (e.g. passing an object into a function without copying it), use a reference.

Wyzard
+1  A: 

References are pointers in disguise, or at least that's a safe way to think of them.

One reason for them is because C and C++ don't have "var" parameters, as in Pascal etc. Using a reference gives you something very close to that, but unlike "var", it can also be used elsewhere - e.g. to give you a quick shorthand for something else...

int& alias = thing.blah [foo]->bar;
handle (alias, alias+1, alias*2);

References are also returned by a lot of functions, meaning the "result" of the function can be written to as well as read, as in...

std::deque<int>  mydeque;
mydeque.push_back (1);
mydeque.back () += 1;  //  increment the top item on the stack

The same functionality could be achieved using a pointer, but a reference is more convenient. The usual term is "syntactic sugar".

A useful (but not completely reliable) fact about references is that you're less likely to accidentally change the underlying pointer, since it takes a bit of work to access that pointer rather than the pointed-to value. This is a helpful hint to choosing - use the one that creates the least clutter in your code.

Steve314