std :: move Vs std :: forward

时间:2016-03-21 21:54:12

标签: c++ c++11 move perfect-forwarding

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

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

但每个答案都不同并且适用并且说的略有不同。所以我很困惑。

我有以下情况。

  • 将项目复制到容器中
    复制项目是C ++ 03所以我很清楚。
  • 将项目构建到容器中
    将构造项置于容器中我相信正确使用完美转发通过两个函数将参数转发给emplaceBackInternal()中的T的构造函数(如果我错了,请另外说明。)
  • 将项目移入容器
    我的问题似乎是理解将物品移入容器。

守则:

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只有一个用例:施放模板化函数参数

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

Answer @Howard Hinnant Score 38

  

如果Y是左值引用,则结果将是左值表达式。 如果Y不是左值参考,则结果将是右值(准确地说是xvalue)表达式。

根据此定义,我可以使用std::movestd::forward

Answer @Bo Persson Score 11

  

std :: forward用于完全按照传递给函数的方式转发参数。

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

1 个答案:

答案 0 :(得分:5)

在这种情况下:

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&&类型的表达式,它始终是一个rvalue。

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

无论哪种方式,我们都会在同一点上结束 - 我们将moveBackInternal称为value施放为左值。只是move()是一种更简单的方法。 forward<T> 有效,但这是不必要的。