std::move 比 std::forward

std::move Vs std::forward

这似乎是已经问过的最相关的问题。

Whats the difference between std::move and std::forward

但每个答案都不同,适用的内容也略有不同。所以我很困惑。

我有以下情况。

代码:

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;
    }
};

我把这三个都包括在这里是为了将这三个函数与前面提到的答案中提供的答案进行比较。主要是moveconstruct长得很像,感觉应该是一样的

Answer @Potatoswatter Score 67

std::forward has a single use case: to cast a templated function parameter

根据这个定义,我应该在 push_back(T&& value) 中使用 std::move 并且 moveBackInternal(T&& value) 因为值不是函数的模板参数。

Answer @Howard Hinnant Score 38

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

根据这个定义,我似乎可以使用 std::movestd::forward

Answer @Bo Persson Score 11

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

似乎说 std::forward 是可以接受的(尽管如果我在答案中遵循 link,所有示例都使用模板函数)。

在这种情况下:

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

}

std::forward<T>(value)std::move(value) 在这种情况下 相同 (1)(2) 之间没有关系。 .. 所以使用 (2))。

move 是对 xvalue 的无条件转换。该行给你一个 T&& 类型的表达式,它总是一个右值。

forward 是条件转换。如果 T 是左值引用类型,它会产生一个左值。否则(如果它不是引用类型或右值引用类型),它会产生一个右值。在我们的例子中,T 不是引用类型 - 所以我们得到一个右值。

无论哪种方式,我们都在同一点结束 - 我们调用 moveBackInternal 并将 value 转换为右值。 move() 是一种更简单的方法。 forward<T>有效,但没有必要。