Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is an xvalue's lifetime extended when it is bound to a const lvalue reference?

If I write the following code:

#include <iostream>

using namespace std;

int main()
{
  cout << &(int &&)123 << endl;
  return 0;
}

Then g++ complains:

foo.cc: In function ‘int main()’:
foo.cc:7:20: error: taking address of xvalue (rvalue reference)

Ok, thanks to What are rvalues, lvalues, xvalues, glvalues, and prvalues? I get that an xvalue means that it's about to "expire", which makes sense. But now if I do this:

#include <iostream>

using namespace std;

int main()
{
  const int &x = (int &&)123;
  cout << &x << endl;
  return 0;
}

This "works" just fine and will print an address. So, I have a few questions:

  1. If the value is about to expire, why can I make a reference to it? The reference won't keep the original object alive (right?).
  2. Does such a reference result in undefined behavior? E.g. because we're referencing an object that may have been destroyed?

In general is there a way to know the lifetime of an rvalue reference?

like image 896
FatalError Avatar asked Feb 27 '12 15:02

FatalError


2 Answers

Perhaps I'm alone but I think that this is not safe:

const int &x = (int &&)123;

The lifetime-lengthening rules apply only when the reference is initialized by an expression that directly refers to a temporary object. In other words, the expression has to carry the "temporary" attribute. If you omit the (int&&), then for binding to the reference, the compiler will implicitly create a prvalue expression that refers to a temporary object which is initialized by the value 123 and lifetime lengthening then applies.

But if you mix rvalue references in between, the compiler has no way to know at compile time whether or not to lengthen the lifetime of the referred-to object.

int a = 0;
const int &x = ((rand() == 42) ? (int&&)123 : (int&&)a);

I therefor think that your code has undefined behavior, because you evaluate a dangling reference (even if only for taking its address).

like image 86
Johannes Schaub - litb Avatar answered Sep 22 '22 13:09

Johannes Schaub - litb


Clause 12.2, paragraphs 4-5, says that the lifetime is extended in the second example

There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression. ...

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
(none of the exceptions apply here)

like image 31
Bo Persson Avatar answered Sep 20 '22 13:09

Bo Persson