std :: move对比std :: forward [英] std::move Vs std::forward

查看:67
本文介绍了std :: move对比std :: forward的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This seems to be most relavant question already asked.

std :: move和std :: forward之间有什么区别

但是每个答案都是不同的,适用的说法略有不同.所以我很困惑.

But each answer is different and applies and says slightly different things. So I am confused.

我有以下情况.

  • 将项目复制到容器中
    复制项目是C ++ 03,所以我对此非常了解.
  • 将项目构造到容器中
    我相信将construct项目放入容器中可以正确地使用完美转发,以通过两个函数将参数转发到emplaceBackInternal()中的T的构造函数(如果我错了,请另外说明).
  • 将项目移入容器
    我的问题似乎是了解将物品移入容器中.
  • Copy item into container
    The Copy item is C++03 so I understand that quite well.
  • Construct item into container
    The Construct item into container I believe uses perfect forwarding correctly to forward the arguments through two functions to the constructor of T in emplaceBackInternal() (Please say otherwise if I am wrong).
  • Move item into container
    My problem seems to be understanding the moving an item into the container.

代码:

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看起来是如此相似,以至于它们应该是相同的.

I include all three here to compare the three functions with the answers provided in the previously mentioned answer. The main reason is that move and construct looks so similar that it feels like they should be the same.

回答@Potatoswatter得分67

std :: forward有一个用例:投射模板化的函数参数

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

By this definition I should be using std::move inside push_back(T&& value) and moveBackInternal(T&& value) as the value is not a template parameter for the function.

回答@Howard Hinnant得分38

如果Y是左值引用,则结果将是一个左值表达式. 如果Y不是左值引用,则结果将是右值(精确到x值)表达式.

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.

Seems by this definition I can use either std::move or std::forward.

回答@Bo Persson得分11

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

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

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

Seems to say that std::forward is acceptable (though if I follow the link in the answer all the examples use templated functions).

推荐答案

在这种情况下:

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)).

std::forward<T>(value) and std::move(value) are identical in this scenario (it doesn't matter between (1) and (2)... so use (2)).

move是无条件强制转换为xvalue.该行始终为您提供类型T&&的表达式,该表达式为右值.

move is an unconditional cast to xvalue. That line gives you an expression of type T&& that's an rvalue, always.

forward是有条件的强制转换.如果T是左值引用类型,则将产生一个左值.否则(如果不是引用类型也不是右值引用类型),则产生右值.在我们的例子中,T不是引用类型-因此我们得到一个右值.

forward is a conditional cast. If T is an lvalue reference type, it yields an lvalue. Otherwise (if it's either not a reference type or an rvalue reference type), it yields an rvalue. In our case, T is not a reference type - so we get an rvalue.

无论哪种方式,我们都在同一点结束-调用moveBackInternal并将value强制转换为右值.只是move()是到达那里的一种更简单的方法. forward<T> 有效,但这不是必需的.

Either way, we end up at the same point - we call moveBackInternal with value cast as an rvalue. Just move() is a simpler way of getting there. forward<T> works, but it's unnecessary.

这篇关于std :: move对比std :: forward的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆