23
votes

While trying to understand how rvalue references work I ended up with this piece of code:

int* iptr = nullptr;
int*&& irr = iptr;

Compiling the above code gives the following error:

error: rvalue reference to type 'int *' cannot bind to lvalue of type 'int *'

I understand this is correct, but why does the following code, where I bind using a void* instead of int*, compiles without any problem? Will the runtime behavior be correct or should I expect undefined behavior?

int* iptr = nullptr;
void*&& irr = iptr;
2

2 Answers

22
votes

This is well-formed.

int* and void* are different types; you can't bind a int* to reference to void* directly. The int* needs to be converted to void* firstly, which is a temporary object and could be bound to rvalue-reference. (PS the lifetime of the temporary is extended to the lifetime of the reference.)

Note that irr doesn't bind to iptr; so any modification on it has nothing to do with iptr.

This is not special for void*, same thing happens for other types, e.g.

char c;
int&& r = c; // a temporary int is constructed from c and then bound to r;
             // its lifetime is extened to the lifetime of r
11
votes

In addition to @songyuanyao answer: you could make an rvalue out of iptr e.g. by means of static_cast:

  int* iptr = nullptr;
  int*&& irr = static_cast<int *>(iptr);