Home  >  Article  >  Backend Development  >  How Does std::move() Handle Lvalues in C ?

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

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-14 14:46:02346browse

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 T>
typename remove_reference<T>::type&& move(T&& arg)
{ return static_cast<typename remove_reference<T>::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<Object>::type&& move(Object&& arg)
{ return static_cast<remove_reference<Object>::type&&>(arg); }

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

Object&& move(Object&& arg) { return static_cast<Object&&>(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<Object&>::type&& move(Object& && arg)
{ return static_cast<remove_reference<Object&>::type&&>(arg); }

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

Object&& move(Object& && arg) { return static_cast<Object&&>(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<Object&&>(arg); }

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

The above is the detailed content of How Does std::move() Handle Lvalues in C ?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn