2016-03-21 59 views
5

这似乎是已经问过的最相关的问题。std :: move VS std ::转发

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

但每次的答案都是不同的,适用,并说略有不同的东西。所以我很困惑。

我有以下情况。

  • 复制项目到容器
    复印产品C++ 03所以我的理解是相当不错的。
  • 构建项目进入容器
    将构建项目进入容器我相信正确使用完美转发通过两个函数转发参数T的构造函数emplaceBackInternal()(请说否则,如果我错了)。
  • 将物品移入容器
    我的问题似乎是将物品移入容器。

验证码:

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 ::向前有一个单一的用例:施放模板函数参数

按照这个定义,我应该使用std::movepush_back(T&& value)moveBackInternal(T&& value)作为值不是函数的模板参数。

Answer @Howard Hinnant Score 38

如果Y是一个左值参考,其结果将是一个左值表达式。 如果Y不是一个左值引用,则结果将是一个右值(xvalue是精确的)表达式。

似乎按此定义,我可以使用std::movestd::forward

Answer @Bo Persson Score 11

的std ::向前来转发参数正是它被传递给函数的方式。

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

+0

呃...你的问题没有被链接的答案回答? – Barry

+0

呃......哪个答案是正确的!每个人都指定了不同的结果。 –

+0

他们都是正确的。两个只是说'std :: forward'的意图是用于转发引用,第三个额外花费一些时间来解释'std :: forward'是什么。 – Barry

回答

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&&的表达式,它总是一个右值。

forward是一个有条件的转换。如果T是一个左值引用类型,则它会产生一个左值。否则(如果它不是一个引用类型或一个右值引用类型),它会产生一个右值。在我们的例子中,T不是引用类型 - 所以我们得到一个右值。无论哪种方式,我们最终都会得到相同的结果 - 我们将moveBackInternalvalue作为右值。只需move()是一个更简单的方法。 forward<T>作品,但没有必要。

+0

有时候,我希望我和你在一个办公室(或者是一个职位的作者),并且可以在白板上坦诚地讨论更好的技术。 - 如果我假定'std :: move'和'std :: forward'完成的所有工作都是编译时工作的。那么解决方案(1)不会更好,因为它使代码看起来与'emplace_back()'完全相同。为什么我需要两种不同的技术,当我可以有一种技术适用于所有情况?差异较小意味着维护代码更容易? –

+0

@LokiAstari似乎主要是基于意见。当我们无条件地移动时,我发现使用'move()'更直接。 'push_back()'代码只能移动,所以为什么要使用更复杂的类型?最终,我发现从根本上来说...关闭...与转发参考。我不知道如何做得更好 - 无论好坏,这都是我们得到的。 – Barry

+0

感谢您的所有意见。说实话,我仍然试图形成我的观点,只是想在这里扮演魔鬼的角色。 :-) –