views:

565

answers:

3

Consider the following:

int ival = 1.01;
int &rval = 1.01; // error: non-const reference to a const value.
int &rval = ival;

rval = 1.01;

The first assignment of &rval to a literal value fails as expected. If I comment out that line the code compiles and runs. I understand why the initialization fails, but I'm confused why the assignment to rval works in the last line. I didn't think it was allowed to assign a reference to a literal value.

EDIT: Thanks for the quick answers. I'm tempted to delete this to hide my shame, but I think I'll leave it here so everyone else can point and laugh.

In my own defense, I'm working through the exercises in a book (C++ Primer) and this problem is about reference initialization. Still, it's pretty embarrassing to have so completely overlooked the point of a reference in the first place. :)

+6  A: 

ival isn't a literal value, 1.01 is the literal value. It's been copied to ival which is a variable, which most definitely can have it's references assigned to another variable.

casperOne
Well, I'm just stupid.
Bill the Lizard
+3  A: 

After the reference is initialized, it is an alias for what it was initialized to. Once a reference is initialized, you cannot change what the reference refers to. However you can change the 'thing' the reference refers to (if the reference is not const).

The last line is in effect setting the variable ival to 1.01 (again).

Michael Burr
Thanks. Ironically, I'm working through the problems in a book that explains how references work in C++. I guess I need to read some more. :)
Bill the Lizard
+3  A: 

Here is something you may be surprised to find that you can do though:

const int& x = 42;        // No error!

C++ does allow initialising a const reference with a literal value (or other rvalue). What actually happens is that the compiler creates a temporary by copying the RHS, and initialises the reference to refer to that temporary. The compiler ensures that the temporary stays alive until scope exit (i.e whenever x goes out of scope in this case).

Note that this doesn't work when initialising member variables of a class.

Tricky huh? :)

j_random_hacker
an important property is that if the left hand side is a reference to base, but the rhs is a derived, the base doesn't need a virtual dtor. At the scope end, the correct (derived) dtor will be called. can be used to write efficient ScopeGuards that execute some functor when scope exits. loki uses it
Johannes Schaub - litb
Yes. I used Alexandrescu's ScopeGuard (slightly modified) to great effect in a GUI Win32 program I wrote a while back -- really makes managing all the different resource handles much easier!
j_random_hacker