"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > How Does std::move() Handle Lvalues in C++?

How Does std::move() Handle Lvalues in C++?

Published on 2024-11-13
Browse:403

How Does std::move() Handle Lvalues in C  ?

What Does std::move() Do to lvalues?

std::move() is a powerful tool in C for facilitating perfect forwarding. Yet its implementation can raise a few eyebrows upon first glance. To clarify how std::move() achieves this, let's delve into the intricacies of its implementation.

Understanding the 'Move' Function

We'll start with the simplified version of the 'move' function template:

template 
typename remove_reference::type&& move(T&& arg)
{ return static_cast::type&&>(arg); }

Case 1: Passing an Rvalue

When std::move() is called with an rvalue (a temporary object or an expression that evaluates to an rvalue), the move template is instantiated as follows:

// move with [T = Object]:
remove_reference::type&& move(Object&& arg)
{ return static_cast::type&&>(arg); }

Since remove_reference converts Object to Object, we end up with:

Object&& move(Object&& arg) { return static_cast(arg); }

As anticipated, the function simply casts its rvalue argument to an rvalue reference.

Case 2: Passing an Lvalue

Now, the interesting case arises when std::move() is invoked with an lvalue (a named variable or an expression that evaluates to an lvalue).

Object a; // a is lvalue
Object b = std::move(a);

This time, the move template instantiates to:

// move with [T = Object&]
remove_reference::type&& move(Object& && arg)
{ return static_cast::type&&>(arg); }

Again, remove_reference converts Object& to Object, resulting in:

Object&& move(Object& && arg) { return static_cast(arg); }

At first glance, this seems counterintuitive since we've passed an lvalue. However, C 11 introduces the concept of reference collapsing, which modifies the interpretation of reference syntax:

  • Object & & = Object &
  • Object & & && = Object &
  • Object & && & = Object &
  • Object & && & && = Object & &&

Under these rules, Object& && effectively behaves as Object&, an ordinary lvalue reference that can bind to lvalues.

Therefore, the final form of the function becomes:

Object&& move(Object& arg) { return static_cast(arg); }

In essence, std::move() casts the lvalue argument to an rvalue reference, enabling perfect forwarding regardless of the input type.

Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3