+6  A: 

Because references represent the variable themselves.

When you make a reference to a variable, you shouldn't thinking of it as "another way of accessing the variable". You should think of it as being the variable itself.

How would you reset a reference, and what use would it be?

EDIT:

For clarification, the problem is in your sentence: "[References] ...always point to the same object."

References do not point; they are. (It just so happens they are implemented using pointers.)

Edit for OP Edit:

You're missing the point of references. Did you read this? A reference is an alias, it's just another way of accessing the same variable.

Here's a main reason:

I have a class that takes up 500 MB of memory, so copying this class is too expensive, which means a function:

void do_something_with_fatty_class(FattyClass c);

Is not an option, since the original class will be copied onto the stack (500 MB!), and the function called. So in C, we did this:

void do_something_with_fatty_class(FattyClass *c);

Which is great: The class is not copied and we can still access it. But the problem is if we don't check for null, doing this:

do_something_with_fatty_class(0);

Will crash. Lots of functions have:

if (!c) return; // return if function was passed null

At the top. The point of references was: You don't need to copy the object, but you also can NEVER* have a "null" reference. You don't need to check for null because it cannot happen, yet you've got the object. You have an alias to the object. Not a copy or pointer.

So reseating them would be bad: how would the syntax look? References are not like pointers, they don't point to an address. There isn't anything to change about a reference because a reference isn't a type. The reference itself takes no memory. The address of the reference is the address of the original, along with the size, operators, etc...it's just another way of getting some data, safely.

Not sure what else to add.

  • Except when people do strange things, like another answer states. But if something does that they deserve a crash.
GMan
using pointers, or compiler magic. The latter is actually common, for instance when a copy constructor is inlined.
MSalters
TheFogger
The thing is the initial = is not operator=. The = can also be: "int i = 0; int" Its just "construction", but remember references are not a type. There is no actual constructor or operator= for the reference; it's just syntax. You cannot do this: "int" because it's referring to nothing.
GMan
+2  A: 

C++ references can sometimes be forced to be 0 with some compilers (it's just a bad idea to do so*, and it violates the standard*).

int &x = *((int*)0); // Illegal but some compilers accept it

EDIT: according to various people who know the standard much better than myself, the above code produces "undefined behavior". In at least some versions of GCC and Visual Studio, I've seen this do the expected thing: the equivalent of setting a pointer to NULL (and causes a NULL pointer exception when accessed).

Mr Fooz
"it's just a bad idea": because the utility of such a critter is, um, limited.
dmckee
It can occur accidentally though, so it's good to know of the possibility. I've harped on this subject before.
Mark Ransom
This code is illegal: in valid C++ code, this must never happen. So no, references CANNOT ever be 0, as guaranteed by the C++ standard.
Konrad Rudolph
C++ references cannot be "0". it's like saying "non-static functions are the same as static functions, because they don't need a object to be called".
Johannes Schaub - litb
Actually references can be NULL, just that as soon as they are used in any way there's the equivalent of a NULL pointer exception raised. I have done this way back in the past and it did create a whole mess of problems. However the fact remains that you can actually set a reference to 0.
Daemin
Nope - the Undefined Behavior already happened at *((int*)0). What happens after that no longer is C++. So don't use C++ terms like reference, NULL or exception for anything that happens afterwards.
MSalters
The "undefined behavior" excuse is fine in discussions like this, but doesn't help when you're trying to track down a bug. While undefined, the behavior is usually quite predictable. And insidious, because the crash is often far removed from the cause.
Mark Ransom
Just to be clear, I agree that the expression *((int*)0) is a bug. But it's going to compile just fine, and your program probably won't crash at that particular spot. See http://stackoverflow.com/questions/57483/difference-between-pointer-variable-and-reference-variable-in-c/57656#57656
Mark Ransom
I and i think others don't say that it will necessarily crash your app. We just say that it's wrong to say that it's "possible to have a reference that is NULL". Just because compilers do allow it in realms of undefined behavior doesn't mean it's allowed by the language.
Johannes Schaub - litb
it's true that originally, the indent was to say that it's valid to dereference the null pointer unless an rvalue was tried to read ( http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232 ), but in fact all the concept of an lvalue is based on entities. There is no such "empty lvalue".
Johannes Schaub - litb
saying that it's possible to have a null reference will confuse people that don't know better, making them believe that the language actually allows that. and i argue that it's actually very helpful to know about it when trying to track down a bug. People that actually count on what C++ guarantees..
Johannes Schaub - litb
.. may read stuff of a reference and then crash because the reference wasn't actually set to anything. I only say what famous herb sutter already said "know what you write and write what you know". make a big fat warning on any answer like that saying "this is invalid - but an interesting insight!".
Johannes Schaub - litb
Core issue 232 is still drafting; it's not in C++2003. In its current state, it would introduce "references to empty lvalues", and those are functionally equivalent to null references.
MSalters
+14  A: 

In C++, it is often said that "the reference is the object". In one sense, it is true: though references are handled as pointers when the source code is compiled, the reference is intended to signify an object that is not copied when a function is called. Since references are not directly addressable (for example, references have no address, & returns the address of the object), it would not semantically make sense to reassign them. Moreover, C++ already has pointers, which handle reseating semantics.

rlbond
I still don't really get the reason why the (in my opinion) useful non-null reseatable reference is not in c++. The problems brought up don't seem difficult to solve, and I think program reliability would increase. Accepting this answer because of the votes.
TheFogger
A: 

I would imagine that it is related to optimization.

Static optimization is much easier when you can know unambiguously what bit of memory a variable means. Pointers break this condition and re-setable reference would too.

dmckee
+3  A: 

It would probably have been less confusing to name C++ references "aliases"? As others have mentioned, references in C++ should be though of as the variable they refer to, not as a pointer/reference to the variable. As such, I can't think of a good reason they should be resettable.

when dealing with pointers, it often makes sense allowing null as a value (and otherwise, you probably want a reference instead). If you specifically want to disallow holding null, you could always code your own smart pointer type ;)

snemarch
+1 for the smart pointer idea; I would have said the same thing. New features aren't considered for the language if it's already possible to accomplish with the existing standard.
Mark Ransom
+3  A: 

The reason that C++ does not allow you to rebind references is given in Stroustrup's "Design and Evolution of C++" :

It is not possible to change what a reference refers to after initialization. That is, once a C++ reference is initialized it cannot be made to refer to a different object later; it cannot be re-bound. I had in the past been bitten by Algol68 references where r1=r2 can either assign through r1 to the object referred to or assign a new reference value to r1 (re-binding r1) depending on the type of r2. I wanted to avoid such problems in C++.

Michael Burr
A: 

Because sometimes things should not be re-pointable. (E.g., the reference to a Singleton.)

Because it's great in a function to know that your argument can't be null.

But mostly, because it allows use to have something that really is a pointer, but which acts like a local value object. C++ tries hard, to quote Stroustrup, to make class instances "do as the ints d". Passing an int by vaue is cheap, because an int fitss into a machine register. Classes are often bigger than ints, and passing them by value has significant overhead.

Being able to pass a pointer (which is often the size of an int, or maybe two ints) that "looks like" a value object allows us to write cleaner code, without the "implementation detail" of dereferences. And, along with operator overloading, it allows us to write classes use syntax similar to the syntax used with ints. In particular, it allows us to write template classes with syntax that can be equally applied to primitive, like ints, and classes (like a Complex number class).

And, with operator overloading especially, there are places were we should return an object, but again, it's much cheaper to return a pointer. Oncve again, returning a reference is our "out.

And pointers are hard. Not for you, maybe, and not to anyone that realizes a pointer is just the value of a memory address. But recalling my CS 101 class, they tripped up a number of students.

char* p = s; *p = *s; *p++ = *s++; i = ++*p;

can be confusing.

Heck, after 40 years of C, people still can't even agree if a pointer declaration should be:

char* p;

or

char *p;
tpdi
The correct way is: char *p. The disagreement is on style, which is subjective.
GMan
@GMan: You have a typo there. You said the correct way is "char *p" where it is obviously "char* p" since the type is pointer-to-char. Just a helpful, erm, pointer. :)
John Dibling
@John: *Unfortunately*, C and C++ syntax rules break declarations into two parts. To illustrate: "char *p, c;" declares 1 pointer-to-char called p and one character (NOT pointer-to-char) called c. I know, yuck. :/
j_random_hacker
John, j_random has the response I would give to that.That's why the total correct way is putting *'s next to the variable name. It just so happens that when declaring only one pointer, either way has the same end result.
GMan
+5  A: 

Because then you'd have no reseatable type which can not be 0. Unless, you included 3 types of references/pointers. Which would just complicate the language for very little gain (And then why not add the 4th type too? Non-reseatable reference which can be 0?)

A better question may be, why would you want references to be reseatable? If they were, that would make them less useful in a lot of situations. It would make it harder for the compiler to do alias analysis.

It seems that the main reason references in Java or C# are reseatable is because they do the work of pointers. They point to objects. They are not aliases for an object.

What should the effect of the following be?

int i = 42;
int& j = i;
j = 43;

In C++ today, with non-reseatable references, it is simple. j is an alias for i, and i ends up with the value 43.

If references had been reseatable, then the third line would bind the reference j to a different value. It would no longer alias i, but instead the integer literal 43 (which isn't valid, of course). Or perhaps a simpler (or at least syntactically valid) example:

int i = 42;
int k = 43;
int& j = i;
j = k;

With reseatable references. j would point to k after evaluating this code. With C++'s non-reseatable references, j still points to i, and i is assigned the value 43.

Making references reseatable changes the semantics of the language. The reference can no longer be an alias for another variable. Instead it becomes a separate type of value, with its own assignment operator. And then one of the most common usages of references would be impossible. And nothing would be gained in exchange. The newly gained functionality for references already existed in the form of pointers. So now we'd have two ways to do the same thing, and no way to do what references in the current C++ language do.

jalf
+1. The key part there is "the newly gained functionality for references already existed in the form of pointers."
j_random_hacker
There *are* already 3 types. The possibly-null, not-reseatable type is `int* const`. For consistency, there should be 4, as possibly-null and reseatable are quite orthogonal.
MSalters
Yes, they're orthogonal, but the language doesn't have to provide every combination. The question is, would the added expressiveness outweigh the added complexity? C++ is more than complex enough as it is, so they need a better reason to add a feature than "it doesn't exist yet".
jalf
+3  A: 

A reference is not a pointer, it may be implemented as a pointer in the background, but its core concept is not equivalent to a pointer. A reference should be looked at like it *is* the object it is referring to. Therefore you cannot change it, and it cannot be NULL.

A pointer is simply a variable that holds a memory address. The pointer itself has a memory address of its own, and inside that memory address it holds another memory address that it is said to point to. A reference is not the same, it does not have an address of its own, and hence it cannot be changed to "hold" another address.

I think the parashift C++ FAQ on references says it best:

Important note: 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.

and again in FAQ 8.5 :

Unlike a pointer, once a reference is bound to an object, it can not be "reseated" to another object. The reference itself isn't an object (it has no identity; taking the address of a reference gives you the address of the referent; remember: the reference is its referent).

Brian R. Bondy
+2  A: 

A reseatable reference would be functionally identical to a pointer.

Concerning nullability: you cannot guarantee that such a "reseatable reference" is non-NULL at compile time, so any such test would have to take place at runtime. You could achieve this yourself by writing a smart pointer-style class template that throws an exception when initialised or assigned NULL:

struct null_pointer_exception { ... };

template<typename T>
struct non_null_pointer {
    // No default ctor as it could only sensibly produce a NULL pointer
    non_null_pointer(T* p) : _p(p) { die_if_null(); }
    non_null_pointer(non_null_pointer const& nnp) : _p(nnp._p) {}
    non_null_pointer& operator=(T* p) { _p = p; die_if_null(); }
    non_null_pointer& operator=(non_null_pointer const& nnp) { _p = nnp._p; }

    T& operator*() { return *_p; }
    T const& operator*() const { return *_p; }
    T* operator->() { return _p; }

    // Allow implicit conversion to T* for convenience
    operator T*() const { return _p; }

    // You also need to implement operators for +, -, +=, -=, ++, --

private:
    T* _p;
    void die_if_null() const {
        if (!_p) { throw null_pointer_exception(); }
    }
};

This might be useful on occasion -- a function taking a non_null_pointer<int> parameter certainly communicates more information to the caller than does a function taking int*.

j_random_hacker
MSalters
good idea doing it with the lvalue. haha.
Johannes Schaub - litb
@MSalters: No, requiring lvalues doesn't guarantee the reseatable reference is non-null any more than initialising a regular reference does -- see 8.3.2.4. E.g.: "int ". There's a world of difference between "x is forbidden" and "x produces undefined behaviour."
j_random_hacker
@MSalters: As a side issue, you could have phrased your comment in a less hostile manner without sacrificing any information content. But you chose not to -- why?
j_random_hacker
8.3.2.4 in fact states exactly what I said: "A null reference cannot exist in a well-defined (C++) program". The C++ standard basically covers two subjects: what is a well-defined C++ program, and how do they behave. "Nasal demons" were invented to make explicit the limits of the standard.
MSalters
And comments are only 300 characters. You'll see that I already abbreviated "reference" to "ref" to make it fit. "Wrong" has many synonyms, many more friendly, but few of those take 5 letters.
MSalters
A statement of the form "A **well-defined** program cannot do x with y" is no more a guarantee that x cannot happen than writing "// Don't do x" in y's header file is, and just as unhelpful. And that is the only "guarantee" your reseatable, non-nullable reference provides -- an empty semantic one.
j_random_hacker
Also, you could have safely abbreviated "WRONG." all the way down to 0 characters.
j_random_hacker
A: 

You can't do this:

int theInt = 0;
int& refToTheInt = theInt;

int otherInt = 42;
refToTheInt = otherInt;

...for the same reason why secondInt and firstInt don't have the same value here:

int firstInt = 1;
int secondInt = 2;
secondInt = firstInt;
firstInt = 3;

assert( firstInt != secondInt );
John Dibling
A: 

I always wondered why they didn't make a reference assignment operator (say :=) for this.

Just to get on someone's nerves I wrote some code to change the target of a reference in a structure.

No, I do not recommend repeating my trick. It will break if ported to a sufficiently different architecture.

Joshua
A: 

Being half serious: IMHO to make them little more different from pointers ;) You know that you can write:

MyClass & c = *new MyClass();

If you could also later write:

c = *new MyClass("other")

would it make sense to have any references alongside with pointers?

MyClass * a =  new MyClass();
MyClass & b = *new MyClass();
a =  new MyClass("other");
b = *new MyClass("another");
A: 

The fact that references in C++ are not nullable is a side-effect of them being just an alias.

hasen j