Hello, I’m Liang Tang.

This is part 38 of the EasyC++ series on rvalue references.

For those who want a better reading experience, visit github repository: EasyLeetCode.

Rvalue references

Lvalue and rvalue

In our previous articles, we covered lvalue references. C++11 introduced rvalue reference on the basis of lvalue reference, because it is a new feature, plus the frequency of use is not very high, there is a certain learning cost.

So let’s forget about references, and let’s look at what an lvalue is and what an rvalue is. It’s actually very simple. The lvalue can take the address, which is to the left of the equals sign. The rvalue doesn’t have an address, it’s to the right of the equals sign.

int a = 4;
Copy the code

Let’s say we define a variable a of type int and make it equal to 4. Where a is to the left of the equals sign, and we can solve for the address of A. And 4 is to the right of the equals sign, so there’s no way to get the address for 4. So a is an lvalue and 4 is an rvalue.

Such as:

int test(a) {
    return 4;
}

int a = test(a);Copy the code

Once again, a is to the left of equals, so there’s a way to take the address as an lvalue. And test() is a temporary value that can’t get an address, it’s an rvalue.

A variable with an address is an lvalue, a constant value without an address, and a temporary variable is an rvalue.

Lvalue references and rvalue references

Once you understand the concept of lvalue and rvalue, it’s easy to look at lvalue reference and rvalue reference. An lvalue reference, as its name implies, is a reference that refers to an lvalue but not to an rvalue.

int a = 4;
int &b = a;		/ / legal
int &c = 4;		/ / illegal
Copy the code

There are exceptions to an lvalue reference, however, where a const lvalue reference can refer to an rvalue:

const int &b = 4;
Copy the code

Because a reference to a const modifier cannot be changed, it can point to an rvalue. If you go through the STL code, you’ll notice that some of these functions take const & just to be able to accommodate constant arguments. For example, push_back in a vector:

void push_back (const value_type& val);
Copy the code

An rvalue reference is similar to an lvalue reference, that is, a reference that refers to an rvalue but not to an lvalue. To distinguish it from an lvalue reference, use ampersand, which is two ampersands. It’s quite confusing, to be honest, because it has the same meaning as and.

int a = 4;
int &&b = 4;	/ / legal
int &&c = a;	/ / illegal
Copy the code

The third line above is illegal because C is an rvalue reference and cannot refer to a leftvalue. What if we have to point? The STD :: Move function can be used to convert an lvalue to an rvalue.

using namespace std;
int a = 4;
int &&c = move(a);
Copy the code

The move function sounds like it means to move, but it does not move variables, just a type conversion.

I don’t know if this is going to make your head explode, but it’s not over yet, and one more thing is important. That is, an lvalue reference and an rvalue reference, both of which are themselves lvalue references:

void test(int && tmp) {
    tmp = 2333;
}

using namespace std;

int a = 4;
int &b = a;
int &&c = 4;

test(a);	/ / illegal
test(b);	/ / illegal
test(c);	/ / illegal
test(move(a));/ / legal
test(move(b));/ / legal
test(move(c));/ / legal
Copy the code

References in C++ are a very large category, with much more detail than lvalue references and rvalue references. Such as universal reference, reference folding, perfect forwarding…