Std :: move vs std :: forward

This seems to be the most common question that has already been asked.

What is the difference between std :: move and std :: forward

But each answer is different and applied and says slightly different things. Therefore, I am confused.

I have the following situation.

  • Copy item to container
    The Copy element is C ++ 03, so I understand it well.
  • Construct an item in a container
    The Construct element in the container, which I suppose uses the correct forwarding correctly to redirect the arguments with two functions to the T constructor in emplaceBackInternal() (say differently if I am wrong).
  • Move item to container
    My problem seems to be understanding the movement of an element in a container.

Code:

 template<typename T> class Container { std::size_t length; T* buffer; public: void push_back(T const& value) { resizeIfRequired(); pushBackInternal(value); } template<typename... Args> void emplace_back(Args&&... args) { resizeIfRequired(); emplaceBackInternal(std::forward<T>(arg)...); } void push_back(T&& value) { resizeIfRequired(); // Is this forward correct or should it be move moveBackInternal(std::forward<T>(value)); } private: void pushBackInternal(T const& value) { // Copy construct object into buffer; new (buffer + length) T(value); ++length; } template<typename... Args) void emplaceBackInternal(Args&&... args) { // Construct object into buffer using arguments; new (buffer + length) T(std::forward<T>(args)...); ++length; } void moveBackInternal(T&& value) { // Move construct object into buffer; // Is this forward correct or should it be move new (buffer + length) T(std::forward<T>(value)); ++length; } }; 

I include all three here to compare the three functions with the answers given in the above answer. The main reason is because move and construct look so similar that they seem to be the same.

Reply @Potatoswatter Score 67

std :: forward has one use case: for adding the templated function parameter

By this definition, I have to use std::move inside push_back(T&& value) and moveBackInternal(T&& value) , since the value is not a template parameter for the function.

Reply @Howard Hinnant Score 38

If Y is a reference to an lvalue, the result is an lvalue expression. If Y is not an lvalue reference, the result will be an rvalue expression (xvalue to exact value).

By this definition, I can use either std::move or std::forward .

Reply @Bo Persson Score 11

std :: forward is used to forward the parameter exactly as it was passed to the function.

It seems that std::forward valid (although if I follow the link in the answer, all examples use template functions).

+5
source share
1 answer

In this case:

 void push_back(T&& value) { resizeIfRequired(); moveBackInternal(std::forward<T>(value)); // (1) moveBackInternal(std::move(value)); // (2) } 

std::forward<T>(value) and std::move(value) identical in this scenario (this does not matter between (1) and (2) ... so use (2) ).

move is an unconditional cast to xvalue. This line gives you an expression of type T&& , which always has a value of r.

forward - conditional cast. If T is a lvalue reference type, it gives an lvalue. Otherwise (if it is not a reference type or an rvalue reference type), it gives the value r. In our case, T not a reference type, so we get an rvalue.

In any case, we end at the same point - we call moveBackInternal value custom as rvalue. Just move() is an easier way to get there. forward<T> works, but it is not necessary.

+5
source

Source: https://habr.com/ru/post/1245514/


All Articles