我什么时候应该向前移动

When should I use forward and move?

本文关键字:移动 什么时候      更新时间:2023-10-16

我有一个对向量进行操作的代码:

template<typename T>
void doVector(vector<T>& v, T&& value) {
    //....
    v.push_back(value);
    //...
}

对于普通的push_back,我需要使用forward(value)move(value)还是仅使用value(根据新的C++11)?它们如何影响性能?

例如,

v.push_back(forward<T>(value));

当第二个参数为lvalue时,当前代码将不会编译,因为T&&将变成X&,这意味着T需要是X&,这反过来意味着std::vector<T>将变成std::vector<X&>,这将与第一个参数std::vector<X> &不匹配。因此,这是一个错误。

我会使用两个模板参数:

template<typename T, typename V>
void doVector(vector<T> & v, V && value) 
{
    v.emplace_back(std::forward<V>(value));
}

由于V可以是与T不同的类型,因此emplace_back使更有意义,因为它不仅解决了问题,还使代码更通用。:-)

现在是下一个改进:由于我们使用的是emplace_back,它从参数value创建类型为T的对象(可能使用构造函数),我们可以利用这一事实,使其变为可变函数:

template<typename T, typename ...V>
void doVector(vector<T> & v, V && ... value) 
{
    v.emplace_back(std::forward<V>(value)...);
}

这是更通用的,因为你可以用它作为:

struct point
{
    point(int, int) {}
};
std::vector<point> pts;
doVector(pts, 1, 2);
std::vector<int> ints;
doVector(ints, 10);

希望能有所帮助。

  1. 如果您需要完美的转发意义,则使用forward(value),保留l值、r值等内容。

  2. 转发非常有用,因为它可以帮助您避免为函数编写多个重载,其中有不同的l-val、r-val和引用参数组合

  3. move(value)实际上是一种类型的强制转换运算符,它将l值强制转换为r值

  4. 在性能方面,两者都避免了对对象进行额外的复制,这是主要的好处。

所以他们确实做了两件不同的事情


当你说普通的push_back时,我不确定你的意思,这是两个签名。

void push_back( const T& value );
void push_back( T&& value );

第一个你可以通过任何正常的l-val,但第二个你必须"移动"一个l-val或向前移动一个r-val。记住,一旦你移动l-val,你就不能使用它

额外的一点是,这里有一个资源似乎很好地解释了r-val-refs的概念和其他与之相关的概念。

正如其他人所建议的,你也可以切换到使用template-back,因为它实际上完美地将参数转发到对象的构造函数,这意味着你可以随心所欲地传递它。

  • 当传递作为转发引用的参数时,请始终使用std::forward
  • 当传递一个r值的参数时,请使用std::move

例如

template <typename T>
void funcA(T&& t) {
    funcC(std::forward<T>(t)); // T is deduced and therefore T&& means forward-ref.
}
void funcB(Foo&& f) {
    funcC(std::move(f)); // f is r-value, use move.
}

这是Scott Meyers的一段精彩视频,解释了转发引用(他称之为通用引用)以及何时使用完美转发和/或std::move:

C++及以后的2012:Scott Meyers-C++11 中的通用参考

有关使用std::forward的更多信息,请参阅此相关问题:使用前向的优点

http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-棉眼-Cpp11 中的通用参考

这段名为IMO的视频对何时使用std::forward和何时使用std::move给出了最好的解释。它提出了通用参考的概念,这是IMO关于移动语义推理的一个非常有用的工具。