Octo
Octo

Reputation: 77

Is a named rvalue reference "ref" a xvalue?

If an xvalue is a value that is at the end of its lifetime, what is a named rvalue reference if not an lvalue or xvalue (because it is not expiring and is movable)?

Upvotes: 0

Views: 200

Answers (1)

digito_evo
digito_evo

Reputation: 3682

Read this part carefully:

In C++11, expressions that:

  1. have identity and cannot be moved from are called lvalue expressions;

  2. have identity and can be moved from are called xvalue expressions;

  3. do not have identity and can be moved from are called prvalue ("pure rvalue") expressions;

  4. do not have identity and cannot be moved from are not used[6].

  • The expressions that have identity are called "glvalue expressions" (glvalue stands for "generalized lvalue"). Both lvalues and xvalues are glvalue expressions.

  • The expressions that can be moved from are called "rvalue expressions". Both prvalues and xvalues are rvalue expressions.

So this means that a named rvalue reference is an lvalue.

Go to https://en.cppreference.com/w/cpp/language/value_category for more info.

According to the link above, one of properties of rvalues is that

Address of an rvalue cannot be taken by built-in address-of operator: &int(), &i++[3], &42, and &std::move(x) are invalid.

Now let's look at an example and take advantage of this property:

#include <iostream>


void getNum( int&& i ) // i is an rvalue reference, meaning that it can
                       // bind to both xvalues and prvalues

{
    std::cout << "i: " << i << " --- Address: " << &i << '\n'; // notice how the
                                                               // & operator works for i
    i += 50;
    std::cout << "i: " << i << " --- Address: " << &i << '\n'; // also here
}

int main()
{
    getNum( 35 ); // in this case, we pass it a prvalue

    std::cout << '\n';

    int number { 23 };             // number is an lvalue
    getNum( std::move( number ) ); // and in this case we pass it an xvalue
                                   // since std::move(number) returns an xvalue
}

The output will be similar to the following:

i: 35 --- Address: 0x4f4b9ff62c
i: 85 --- Address: 0x4f4b9ff62c

i: 23 --- Address: 0x4f4b9ff628
i: 73 --- Address: 0x4f4b9ff628

As you can see, the address of operator& does in fact return the address of i. This clearly shows that a variable of type rvalue reference T&& is an lvalue.

Upvotes: 2

Related Questions