Why is it illegal/immoral to reseat a reference? [duplicate] - c++

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Why are references not reseatable in C++
I am trying to more or less swap two reference variables (as practice, I could have swapped the actual variables). I tried doing this by making a temporary variable and making one of the references equal the other, but this got shot down by the compiler. Here is an example:
void Foo()
{
//code
int& ref1 = a;
int& ref2 = b;
int temp;
temp = ref1;
ref1 = ref2;
ref2 = temp;
//or, better yet
std::swap(ref1, ref2);
}
I got an error, and looked on the faq lite. It details that they cannot be reseated, but does not explain why. Why?
Here is a link to the Faq Lite for reference (<---, get it?).

Because there is no syntax to do it:
int x = 0;
int y = 1;
int & r = x;
Now if I say:
r = y;
I assign the value of y to x. If I wanted to reseat I would need some special syntax:
r #= y; // maybe?
As the main reason for using references is as parameters and return types of functions, where this is not an issue, it didn't seem to C++'s designers that this was a path worth going down.

A reference is an alias to object.
Alias can not be changed (we are not spies ;-)

Because references don't have an address of their own (if they do that is implementation dependent, and you can't access them with the & operator directly).
The & operator is used to get the address of the thing that the reference is referring to.
Whereas a pointer does have an address of its own and you can access it with the & operator.
int x = 4;
int *p = &x;
//p holds the address of x
//&p holds the address of p.
int &r = x;
//&r holds the address of x
And if something doesn't have an address of its own then it can't store a value inside of it. And if it can't store a value inside of it, then it can't be changed.
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).

Look at your code again:
temp = ref1;
ref2 = temp;
ref1 = ref2;
References are aliases. All operations that you do on the reference are performed on the object it references. In your code above, how should the compiler magically know that you aren't trying to assign the values to referenced variables, but are rather trying to change the reference itself? There's no syntax to indicate the difference between that, and, for example:
ref1 = 3;
which you'd normally expect to assign a value 3 to the object referenced by ref1.
In short, this is simply by design. If you want "reseatable" references, then you just use pointers (or, if you want to avoid accidential pointer arithmetic, boost::optional).

Unlike pointers, references are designed to guarantee that they always refer to an object. To meet this gaurantee, the compiler requires that all references be initialized in their declaration and disallows you from reassigning them.
Similar to pointers, reference variables allow you to access the same instance of an object through multiple locations - but unlike pointers, reference provide a greater level of safety.

Related

Why can't we reassign the reference [duplicate]

C++ references have two properties:
They always point to the same object.
They can not be 0.
Pointers are the opposite:
They can point to different objects.
They can be 0.
Why is there no "non-nullable, reseatable reference or pointer" in C++? I can't think of a good reason why references shouldn't be reseatable.
Edit:
The question comes up often because I usually use references when I want to make sure that an "association" (I'm avoiding the words "reference" or "pointer" here) is never invalid.
I don't think I ever thought "great that this ref always refers to the same object". If references were reseatable, one could still get the current behavior like this:
int i = 3;
int& const j = i;
This is already legal C++, but meaningless.
I restate my question like this: "What was the rationale behind the 'a reference is the object' design? Why was it considered useful to have references always be the same object, instead of only when declared as const?"
Cheers, Felix
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++.
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 handles the semantics of re-setting.
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.
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).
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*.
Intrestingly, many answers here are a bit fuzzy or even beside the point (e.g. it's not because references cannot be zero or similar, in fact, you can easily construct an example where a reference is zero).
The real reason why re-setting a reference is not possible is rather simple.
Pointers enable you to do two things: To change the value behind the pointer (either through the -> or the * operator), and to change the pointer itself (direct assign =). Example:
int a;
int * p = &a;
Changing the value requires dereferencing: *p = 42;
Changing the pointer: p = 0;
References allow you to only change the value. Why? Since there is no other syntax to express the re-set. Example:
int a = 10;
int b = 20;
int & r = a;
r = b; // re-set r to b, or set a to 20?
In other words, it would be ambiguous if you were allowed to re-set a reference. It makes even more sense when passing by reference:
void foo(int & r)
{
int b = 20;
r = b; // re-set r to a? or set a to 20?
}
void main()
{
int a = 10;
foo(a);
}
Hope that helps :-)
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 ;)
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).
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 );
This is not actually an answer, but a workaround for this limitation.
Basically, when you try to "rebind" a reference you are actually trying to use the same name to refer to a new value in the following context. In C++, this can be achieve by introducing a block scope.
In jalf's example
int i = 42;
int k = 43;
int& j = i;
//change i, or change j?
j = k;
if you want to change i, write it as above. However, if you want to change the meaning of j to mean k, you can do this:
int i = 42;
int k = 43;
int& j = i;
//change i, or change j?
//change j!
{
int& j = k;
//do what ever with j's new meaning
}
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.
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;
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.
The fact that references in C++ are not nullable is a side-effect of them being just an alias.
I agree with the accepted answer.
But for constness, they behave much like pointers though.
struct A{
int y;
int& x;
A():y(0),x(y){}
};
int main(){
A a;
const A& ar=a;
ar.x++;
}
works.
See
Design reasons for the behavior of reference members of classes passed by const reference
There's a workaround if you want a member variable that's a reference and you want to be able to rebind it. While I find it useful and reliable, note that it uses some (very weak) assumptions on memory layout. It's up to you to decide whether it's within your coding standards.
#include <iostream>
struct Field_a_t
{
int& a_;
Field_a_t(int& a)
: a_(a) {}
Field_a_t& operator=(int& a)
{
// a_.~int(); // do this if you have a non-trivial destructor
new(this)Field_a_t(a);
}
};
struct MyType : Field_a_t
{
char c_;
MyType(int& a, char c)
: Field_a_t(a)
, c_(c) {}
};
int main()
{
int i = 1;
int j = 2;
MyType x(i, 'x');
std::cout << x.a_;
x.a_ = 3;
std::cout << i;
((Field_a_t&)x) = j;
std::cout << x.a_;
x.a_ = 4;
std::cout << j;
}
This is not very efficient as you need a separate type for each reassignable reference field and make them base classes; also, there's a weak assumption here that a class having a single reference type won't have a __vfptr or any other type_id-related field that could potentially destroy runtime bindings of MyType. All the compilers I know satisfy that condition (and it would make little sense not doing so).
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");

Pointers vs references examples, which is better in what cases

I'm beggining my programming learning and currently i'm wondering of difrences between pointers and references in C++. For exapmle we can use pointer to return more then one value from function (because as far as i know return can only give us one value) so here is one feature that pointer give us, but probably we can make the same using references.
Now i have questions:
What are the most common and easy to undestand cases in which i
should use pointers and in which i shoud use references?
Which are better to use if I have to my program as safe and as fast as possible?
Thank you for all answers! I hope you'll help me learn and undesrtand every aspect of programming in C++ :)
A pointer is a variable that holds memory address of another variable. A pointer needs to be dereferenced with * operator to access the memory location it points to.
A reference variable is an alias, that is, another name for an already existing variable. A reference, like a pointer is also implemented by storing the address of an object.
A reference can be thought of as a constant pointer (not to be confused with a pointer to a constant value!) with automatic indirection, i.e the compiler will apply the * operator for you.
Differences :
Reassignment: A pointer can be re-assigned. This property is useful for implementation of data structures like linked list, tree, etc. See the following examples:
int x = 5;
int y = 6;
int *p;
p = &x;
p = &y;
On the other hand, a reference cannot be re-assigned, and must be assigned at initialization.
int x = 5;
int y = 6;
int &r = x;

Modifying reference variables, not the variable they alias [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ Reference, change the refered variable
I know that references in c++ are just pointers that get dereferenced for you when you use them. This question is about how to access the underlying pointer and change it.
Consider this code:
int x;
int& x_ref = x; //now equivalent to x
int* x_ptr = &x; //stores address of x
int* x_ref_ptr = &x_ref; //ALSO stores address of x
int&* x_ref_ptr_ref = ???; //what would this mean?
I'm trying to change where a reference points after initialization. I have no concern for type safety or proper practices. Does the c++ language have any tool to let me accomplish this?
There is no pointer to reference, it's ill-formed. A reference is an alias to an object. How would a pointer to an alias work?
Also, it's a feature of the language that a reference can't be reseated. A reseatable reference is a pointer.
This is not possible by design. By using a reference instead of a pointer, you decide to never change its target after declaration, with all entailing drawbacks and advantages (one of which is its "automatic dereferencing". Read the Wikipedia entry on references carefully.
You will need to switch to pointers.

Why do parameters passed by reference in C++ not require a dereference operator?

I'm new to the C++ community, and just have a quick question about how C++ passes variables by reference to functions.
When you want to pass a variable by reference in C++, you add an & to whatever argument you want to pass by reference. How come when you assign a value to a variable that is being passed by reference why do you say variable = value; instead of saying *variable = value?
void add_five_to_variable(int &value) {
// If passing by reference uses pointers,
// then why wouldn't you say *value += 5?
// Or does C++ do some behind the scene stuff here?
value += 5;
}
int main() {
int i = 1;
add_five_to_variable(i);
cout << i << endl; // i = 6
return 0;
}
If C++ is using pointers to do this with behind the scenes magic, why aren't dereferences needed like with pointers? Any insight would be much appreciated.
When you write,
int *p = ...;
*p = 3;
That is syntax for assigning 3 to the object referred to by the pointer p. When you write,
int &r = ...;
r = 3;
That is syntax for assigning 3 to the object referred to by the reference r. The syntax and the implementation are different. References are implemented using pointers (except when they're optimized out), but the syntax is different.
So you could say that the dereferencing happens automatically, when needed.
C++ uses pointers behind the scenes but hides all that complication from you. Passing by reference also enables you to avoid all the problems asssoicated with invalid pointers.
When you pass an object to a function by reference, you manipulate the object directly in the function, without referring to its address like with pointers. Thus, when manipulating this variable, you don't want to dereference it with the *variable syntax. This is good practice to pass objects by reference because:
A reference can't be redefined to point to another object
It can't be null. you have to pass a valid object of that type to the function
How the compiler achieves the "pass by reference" is not really relevant in your case.
The article in Wikipedia is a good ressource.
There are two questions in one, it seems:
one question is about syntax: the difference between pointer and reference
the other is about mechanics and implementation: the in-memory representation of a reference
Let's address the two separately.
Syntax of references and pointers
A pointer is, conceptually, a "sign" (as road sign) toward an object. It allows 2 kind of actions:
actions on the pointee (or object pointed to)
actions on the pointer itself
The operator* and operator-> allow you to access the pointee, to differenciate it from your accesses to the pointer itself.
A reference is not a "sign", it's an alias. For the duration of its life, come hell or high water, it will point to the same object, nothing you can do about it. Therefore, since you cannot access the reference itself, there is no point it bothering you with weird syntax * or ->. Ironically, not using weird syntax is called syntactic sugar.
Mechanics of a reference
The C++ Standard is silent on the implementation of references, it merely hints that if the compiler can it is allowed to remove them. For example, in the following case:
int main() {
int a = 0;
int& b = a;
b = 1;
return b;
}
A good compiler will realize that b is just a proxy for a, no room for doubts, and thus simply directly access a and optimize b out.
As you guessed, a likely representation of a reference is (under the hood) a pointer, but do not let it bother you, it does not affect the syntax or semantics. It does mean however that a number of woes of pointers (like access to objects that have been deleted for example) also affect references.
The explicit dereference is not required by design - that's for convenience. When you use . on a reference the compiler emits code necessary to access the real object - this will often include dereferencing a pointer, but that's done without requiring an explicit dereference in your code.

Why are references not reseatable in C++

C++ references have two properties:
They always point to the same object.
They can not be 0.
Pointers are the opposite:
They can point to different objects.
They can be 0.
Why is there no "non-nullable, reseatable reference or pointer" in C++? I can't think of a good reason why references shouldn't be reseatable.
Edit:
The question comes up often because I usually use references when I want to make sure that an "association" (I'm avoiding the words "reference" or "pointer" here) is never invalid.
I don't think I ever thought "great that this ref always refers to the same object". If references were reseatable, one could still get the current behavior like this:
int i = 3;
int& const j = i;
This is already legal C++, but meaningless.
I restate my question like this: "What was the rationale behind the 'a reference is the object' design? Why was it considered useful to have references always be the same object, instead of only when declared as const?"
Cheers, Felix
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++.
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 handles the semantics of re-setting.
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.
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).
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*.
Intrestingly, many answers here are a bit fuzzy or even beside the point (e.g. it's not because references cannot be zero or similar, in fact, you can easily construct an example where a reference is zero).
The real reason why re-setting a reference is not possible is rather simple.
Pointers enable you to do two things: To change the value behind the pointer (either through the -> or the * operator), and to change the pointer itself (direct assign =). Example:
int a;
int * p = &a;
Changing the value requires dereferencing: *p = 42;
Changing the pointer: p = 0;
References allow you to only change the value. Why? Since there is no other syntax to express the re-set. Example:
int a = 10;
int b = 20;
int & r = a;
r = b; // re-set r to b, or set a to 20?
In other words, it would be ambiguous if you were allowed to re-set a reference. It makes even more sense when passing by reference:
void foo(int & r)
{
int b = 20;
r = b; // re-set r to a? or set a to 20?
}
void main()
{
int a = 10;
foo(a);
}
Hope that helps :-)
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 ;)
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).
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 );
This is not actually an answer, but a workaround for this limitation.
Basically, when you try to "rebind" a reference you are actually trying to use the same name to refer to a new value in the following context. In C++, this can be achieve by introducing a block scope.
In jalf's example
int i = 42;
int k = 43;
int& j = i;
//change i, or change j?
j = k;
if you want to change i, write it as above. However, if you want to change the meaning of j to mean k, you can do this:
int i = 42;
int k = 43;
int& j = i;
//change i, or change j?
//change j!
{
int& j = k;
//do what ever with j's new meaning
}
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.
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;
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.
The fact that references in C++ are not nullable is a side-effect of them being just an alias.
I agree with the accepted answer.
But for constness, they behave much like pointers though.
struct A{
int y;
int& x;
A():y(0),x(y){}
};
int main(){
A a;
const A& ar=a;
ar.x++;
}
works.
See
Design reasons for the behavior of reference members of classes passed by const reference
There's a workaround if you want a member variable that's a reference and you want to be able to rebind it. While I find it useful and reliable, note that it uses some (very weak) assumptions on memory layout. It's up to you to decide whether it's within your coding standards.
#include <iostream>
struct Field_a_t
{
int& a_;
Field_a_t(int& a)
: a_(a) {}
Field_a_t& operator=(int& a)
{
// a_.~int(); // do this if you have a non-trivial destructor
new(this)Field_a_t(a);
}
};
struct MyType : Field_a_t
{
char c_;
MyType(int& a, char c)
: Field_a_t(a)
, c_(c) {}
};
int main()
{
int i = 1;
int j = 2;
MyType x(i, 'x');
std::cout << x.a_;
x.a_ = 3;
std::cout << i;
((Field_a_t&)x) = j;
std::cout << x.a_;
x.a_ = 4;
std::cout << j;
}
This is not very efficient as you need a separate type for each reassignable reference field and make them base classes; also, there's a weak assumption here that a class having a single reference type won't have a __vfptr or any other type_id-related field that could potentially destroy runtime bindings of MyType. All the compilers I know satisfy that condition (and it would make little sense not doing so).
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");