Vicky
Vicky

Reputation: 13244

What is a good way to think about C++ references?

I've been programming C, mainly in an embedded environment, for years now and have a perfectly good mental model of pointers - I don't have to explicitly think about how to use them, am 100% comfortable with pointer arithmetic, arrays of pointers, pointers-to-pointers etc.

I've written very little C++ and really don't have a good way of thinking about references. I've been advised in the past to "think of them as pointers that can't be NULL" but this question shows that that is far from the full story.

So for more experienced C++ programmers - how do you think of references? Do you think of them as a special sort of pointer, or as their own thing entirely? What's a good way for a C programmer to get their head round the concept?

Upvotes: 8

Views: 724

Answers (12)

sbi
sbi

Reputation: 224129

From a syntactic POV, a reference is an alias for an existing object. From a semantic POV, a reference behaves like a pointer with a few problems (invalidation, ownership etc.) removed and an object-like syntax added. From a practical POV, prefer references unless you have the need to say "no object". (Resource ownership isn't a reason to prefer pointers, as this should be done using smart pointers.)

Update: Here's one additional difference between references and pointers which I forgot about: A temporary object (an rvalue) bound to a const reference will have its life-time extended to the life of the reference:

const std::string& result = function_returning_a_string();

Here, the temporary returned by the function is bound to result and will not cease to exist at the end of the expression, but will exist until result dies. This is nice, because in the absence of rvalue references and overloading based on them (as in C++11), this allows you to get rid of one unnecessary copy in the above example.

This is a rule introduced especially for const references and there's no way to achieve this with pointers.

Upvotes: 0

Artem Barger
Artem Barger

Reputation: 41232

I've get used to think about references as an alias for main object.

EDIT(Due to request in comments):

I used to think about reference as kind of aliasing is because it behaves in the exact same way as the original variable without any need to make an extra manipulation in order to affect the variable referenced.

Upvotes: 12

Jamol
Jamol

Reputation: 2291

If you use linux, you can think of references as hard links and pointers as symbolic links (symlinks). Hard link is just another name for a file. The file gets "deleted" when all hard links to this file are removed.

Same about references. Just substitue "hard link" with "reference" and "file" with "value" (or probably "memory location"?).

A variable gets destroyed when all references are gone out of scope.

You can't create a hard link to a nonexistent file. Similary, it's not possible to create a reference to nothing.

However you can create a symlink to a nonexistent file. Much like an uninitialized pointer. Actually uninitialized pointers do point to some random locations (correct me if I'm wrong). But what I mean is that you are not supposed to use them :)

Upvotes: 0

AshleysBrain
AshleysBrain

Reputation:

References are pointer-consts with different syntax. ie. the reference T& is pretty much T * const as in, the pointer cannot be changed. The content of both is identical - a memory address of a T - and neither can be changed.

Then apart from that pretty much the only difference is the syntax: . for references and -> and * for pointer.

That's it really - references ARE pointers, just with different syntax (and they're const).

Upvotes: 3

Will
Will

Reputation: 75665

I think your mental model of pointers, and then a list of all the edge cases you've encountered, is the best way.

Those who don't get pointers are going to fare far worse.

Incidentally, they can be NULL or any other non-accessible memory location (it just takes effort):

char* test = "aha";
char& ok = *test;
test = NULL;
char& bad = *test;

Upvotes: 2

Binary Worrier
Binary Worrier

Reputation: 51711

For me, when I see a pointer in code (as a local variable in a function or a member on a class), I have to think about

  1. Is the pointer null, or is it valid
  2. Who created the object it points to (is it me?, have I done it yet?)
  3. Who is responsible for deleting the object
  4. Does it always point to the same object

I don't have to think about any of that stuff if it's a reference, it's somebody else's problem (i.e. think of a reference as an SEP Field for a pointer)

P.S. Yes, it's probably still my problem, just not right now

Upvotes: 9

EFraim
EFraim

Reputation: 13028

One way to think about them is as importing another name for an object from a possibly different scope.

For instance : Obj o; Obj& r = o; There is really little difference between semantics of o and r.

The major one seems that the compiler watches the scope of o for calling the destructor.

Upvotes: 1

Markus Koivisto
Markus Koivisto

Reputation: 609

In general you just don't think about references. You use references in every function unless you have a specific need for calling by value or pointer magic.

References are essentially pointers that always point to the same thing. A reference doesn't need to be dereferenced, and can instead be accessed as a normal variable. That's pretty much all that there is to it. You use pointers when you need to do pointer arithmetic or change what the pointer points to, and references for just about everything else.

Upvotes: 5

Kim Gräsman
Kim Gräsman

Reputation: 7596

I'm not all too fond of the "ever-valid" view, as references can become invalid, e.g.

int* p = new int(100);
int& ref = *p;

delete p; // oops - ref now references garbage

So, I think of references as non-rebindable (that is, you can't change the target of a reference once it's initialized) pointers with syntactic sugar to help me get rid of the "->" pointer syntax.

Upvotes: 6

DanDan
DanDan

Reputation: 10562

I think of the reference as being the object it refers to. You access the object using . symantecs (as opposed to ->), re-enforcing this idea for me.

Upvotes: 2

Greg Hewgill
Greg Hewgill

Reputation: 993901

How about "pointers that can't be NULL and can't be changed after initialisation". Also, they have no size by themselves (because they have no identity of themselves).

Upvotes: 2

Anders Rune Jensen
Anders Rune Jensen

Reputation: 3806

I think of it as a pointer container.

Upvotes: 0

Related Questions