What Is Std::Move(), and When Should It Be Used

What is std::move(), and when should it be used?

Wikipedia Page on C++11 R-value references and move constructors

  1. In C++11, in addition to copy constructors, objects can have move constructors.

    (And in addition to copy assignment operators, they have move assignment operators.)
  2. The move constructor is used instead of the copy constructor, if the object has type "rvalue-reference" (Type &&).
  3. std::move() is a cast that produces an rvalue-reference to an object, to enable moving from it.

It's a new C++ way to avoid copies. For example, using a move constructor, a std::vector could just copy its internal pointer to data to the new object, leaving the moved object in an moved from state, therefore not copying all the data. This would be C++-valid.

Try googling for move semantics, rvalue, perfect forwarding.

Why do you use std::move when you have && in C++11? [duplicate]

First, there's probably a misconception in the question I'll address:

Whenever you see T&& t in code (And T is an actual type, not a template type), keep in mind the value category of t is an lvalue(reference), not an rvalue(temporary) anymore. It's very confusing. The T&& merely means that t is constructed from an object that was an rvalue 1, but t itself is an lvalue, not an rvalue. If it has a name (in this case, t) then it's an lvalue and won't automatically move, but if it has no name (the result of 3+4) then it is an rvalue and will automatically move into it's result if it can. The type (in this case T&&) has almost nothing to do with the value category of the variable (in this case, an lvalue).

That being said, if you have T&& t written in your code, that means you have a reference to a variable that was a temporary, and it is ok to destroy if you want to. If you need to access the variable multiple times, you do not want to std::move from it, or else it would lose it's value. But the last time you acccess t it is safe to std::move it's value to another T if you wish. (And 95% of the time, that's what you want to do). All of this also applies to auto&& variables.

1. if T is a template type, T&& is a forwarding reference instead, in which case you use std::forward<T>(t) instead of std::move(t) the last time. See this question.

When do you need to explicitly call std::move and when not in cpp?

When do you need to explicitly call std::move and when not in cpp?

In short, and technically precise words: Use std::move when you have an lvalue that you want to be an rvalue. More practically: You would want to do that when there is a copy that you want instead to be a move. Hence the name std::move.

In the example, you return an automatic variable. There is no copy that can be avoided by using std::move because in the special case of returning an automatic variable, there will be a move even from an lvalue.

Here I show the move constructor and the function that I thought would use it. It doesn't.

Just because there is a move in the abstract machine, doesn't necessarily mean that there would be a call to the move constructor. This is a good thing because doing nothing can potentially be faster than calling the move constructor.

This is known as (Named) Return Value Optimization. Or more generally copy elision. Using std::move inhibits this optimization, so not only is it unnecessary in this case, but it is also counter productive.

What does std::move do when called on a function?

Look carefully at A's constructor:

A::A (std::function<void(Timer *, const TimerContext&)> cb)

The function, cb is being passed by value. That means a copy of the function has already occurred from when it was invoked via new:

A *a = new A{customCallback};

The std::move in the constructor initializer list exists to avoid a redundant copy into the member variable. The original function defined by the caller who invoked new A remains unmoved. This is preferred because copying a std::function variable can be expensive. (sizeof(cb) - might be way bigger than you expected).

An alternative implementation: The function could have been passed as a const reference and allow the copy to occur in the constructor itself:

A::A (const std::function<void(Timer *, const TimerContext&)>& cb) : callback_{cb}

Reason to use std::move on rvalue reference parameter

isn't the std::move here unnecessary?

No. Types and value categories are different things.

(emphasis mine)

Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category.

The following expressions are lvalue expressions:

the name of a variable, a function, a template parameter object (since
C++20), or a data member, regardless of type, such as std::cin or
std::endl. Even if the variable's type is rvalue reference, the
expression consisting of its name is an lvalue expression
;

std::move converts lvalue to rvalue (xvalue). As a named variable, x is an lvalue, std::move converts it to rvalue in objects[size++] = std::move(x); then the move assignment operator is supposed to be used. Otherwise, copy assignment operator will be used instead; lvalue can't be bound to rvalue reference.

we still need to use std::move on its member if we want to call move instead of copy right?

Yes, same reason as above.

What happens when std::move() is called without assignment [duplicate]

std::move() doesn't move the passed object by itself; it just possibly enables move semantics for the object. It consists of a cast whose result you can use to select – if possible – the proper overload that supports move semantics. Therefore, in your code:

std::string s = "Moving";
std::move(s);

std::move(s) above casts s to an rvalue reference. The result of the casting is not used. The object s above is not actually moved, and it isn't modified.

Is it still necessary to use std move even if auto && has been used

If you indeed want to move all elements from myMap into anotherMap then yes you must call std::move(). The reason is that element here is still an lvalue. Its type is rvalue reference as declared, but the expression itself is still an lvalue, and thus the overload resolution will give back the lvalue reference constructor better known as the copy constructor.

This is a very common point of confusion. See for example this question.

Always keep in mind that std::move doesn't actually do anything itself, it just guarantees that the overload resolver will see an appropriately-typed rvalue instead of an lvalue associated with a given identifier.

Usages of std::move

You can see most of the std::moves are required by removing them, your code wont compile. The only exceptions are Move 1 and Move 2, the code will still compile without them but only because the std::vector copy constructor is invoked instead.

If you want to move from an object you almost always need to use std::move, the only exceptions are when moving from a temporary and when returning an object.



Related Topics



Leave a reply



Submit