Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is it possible to get a reference to an rvalue?

I have used std::move and std::forward in C++. My question is: how are these functions actually implemented by the standard library?

If an lvalue is something you can get the address of, and an rvalue is exclusively not an lvalue, how can you actually implement these references?

Do these new facilities allow for something like:

auto x = &(3); 

or something like that? Can you get a reference to an rvalue that isn't just a std::move/forward returned lvalue?

Hopefully these questions make sense. I couldn't find good information on Google, just tutorials on perfect forwarding, etc.

like image 273
user3816764 Avatar asked Feb 11 '15 15:02

user3816764


2 Answers

How is it possible to get a reference to an rvalue?

Conceptually, an rvalue expression creates a temporary object, or sometimes denotes an existing object. That can be bound to a reference like any other object; but, to avoid confusion, the language only allows that for rvalue and const lvalue references.

I have used std::move and std::forward in C++. My issue is how this is actually implemented by the compiler?

move simply returns an rvalue reference to its argument, equivalent to

static_cast<typename remove_reference<T>::type&&>(t)

The result of the function call is an rvalue (specifically, an xvalue), so it can be bound to an rvalue reference where the function argument couldn't. This allows you to explicitly move from an lvalue, using move to convert it to an rvalue, while not allowing you to accidentally move from it.

forward is similar, but overloaded to return an rvalue reference to an rvalue or rvalue reference, and an lvalue reference to anything else.

If an l-value is something you can get the address of

That's more or less correct. The official definition is that the expression "designates a function or an object", and those are things that have addresses.

and an r-value is exclusively not an l-value

Not really. Simplifying slightly, an expression is either a lvalue or an rvalue, but can be converted from one to the other. An lvalue can be implicitly converted to an rvalue; converting the other way can be done with a cast, as move does.

how can you actually implement these references?

Just like any other reference - as an alias for, or a pointer to, the object it's bound to. The only difference is which kinds of expression can be used to denote (and possibly create) the object that's bound to the reference.

Do these new facilities allow for something like auto x = &(3);

That attempts to take the address of an rvalue directly, which isn't allowed. Since the question is about references, not pointers, the following are allowed, binding a reference to a temporary object (whose lifetime is extended to match the reference):

auto && rvalue = 3;
auto const & const_lvalue = 3;

while it's not allowed to bind it to a non-const lvalue reference

auto & lvalue = 3;  // ERROR
like image 133
Mike Seymour Avatar answered Sep 27 '22 01:09

Mike Seymour


I cannot call a function: void foo(string* bar) like this: foo(&string("Hello World!")) or I get an error:

error: taking address of temporary

I also cannot call a function: void foo(string& bar) like this: foo(string("Hello World!")) or I get an error:

error: invalid initialization of non-const reference of type 'std::string& {aka std::basic_string&}' from an rvalue of type 'std::string {aka std::basic_string}'

What C++11 has provided me the ability to do is to make an rvalue reference, so I can call a function: void foo(string&& bar) like this: foo(string("Hello World!"));

Furthermore, internally to foo I can get the address of the object passed in by an rvalue reference:

void foo(string&& bar){
    string* temp = &bar;

    cout << *temp << " @:" << temp << endl;
}

It seems like the OP has a really good grip on rvalues. But this explanation of them was helpful to me, and may be to others. It goes into a bit of detail about why C++03 allowed constant references to rvalues, versus C++11's rvalue references.

like image 38
Jonathan Mee Avatar answered Sep 26 '22 01:09

Jonathan Mee