简体   繁体   English

什么时候应该使用前进和移动?

[英]When should I use forward and move?

I have a code that operates on a vector: 我有一个操作矢量的代码:

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

For normal push_back , do I need to use forward(value) , move(value) or just value (according to new C++11) ? 对于普通的push_back ,我是否需要使用forward(value)move(value)或者只是value (根据新的C ++ 11)? and how do they impact the performance? 它们如何影响性能?

For example, 例如,

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

The current code will not compile when the second argument is lvalue because T&& will turn out to be X& which means T needs to be X& which in turn means std::vector<T> will become std::vector<X&> which will NOT match the first argument which is std::vector<X> & . 当第二个参数是左值时,当前代码将无法编译,因为T&&将变为X&这意味着T需要为X&这意味着std::vector<T>将成为std::vector<X&> ,这将不会匹配第一个参数是std::vector<X> & Hence, it is an error. 因此,这是一个错误。

I would use two template parameters: 我会使用两个模板参数:

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

Since V could a different type from T , so emplace_back makes more sense, because not only it solves the problem, it makes the code more generic. 由于V可以是与T不同的类型,因此emplace_back 更有意义,因为它不仅解决了问题,而且使代码更通用。 :-) :-)

Now the next improvement : since we're using emplace_back which creates the object of type T from argument value (possibly using constructor), we could take advantage of this fact, and make it variadic function: 现在是下一个改进:因为我们正在使用emplace_back从参数value创建类型T的对象(可能使用构造函数),我们可以利用这个事实,并使其成为可变函数:

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

That is even more generic, as you could use it as: 这更加通用,因为您可以将其用作:

struct point
{
    point(int, int) {}
};

std::vector<point> pts;
doVector(pts, 1, 2);

std::vector<int> ints;
doVector(ints, 10);

Hope that helps. 希望有所帮助。

  1. forward(value) is used if you need perfect forwarding meaning, preserving things like l-value, r-value. 如果您需要完美的转发含义,则使用forward(value) ,保留l值,r值等内容。

  2. forwarding is very useful because it can help you avoid writing multiple overloads for functions where there are different combinations of l-val, r-val and reference arguments 转发非常有用,因为它可以帮助您避免为具有l-val,r-val和引用参数的不同组合的函数编写多个重载

  3. move(value) is actually a type of casting operator that casts an l-value to an r-value move(value)实际上是一种将l值转换为r值的转换运算符

  4. In terms of performances both avoid making extra copies of objects which is the main benefit. 在性能方面,都避免制作额外的物品副本,这是主要的好处。

So they really do two different things 所以他们真的做了两件事


When you say normal push_back, I'm not sure what you mean, here are the two signatures. 当你说普通的push_back时,我不确定你的意思,这里有两个签名。

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

the first one you can just pass any normal l-val, but for the second you would have to "move" an l-val or forward an r-val. 第一个你可以通过任何正常的l-val,但是对于第二个你必须“移动”一个l-val或向前一个r-val。 Keep in mind once you move the l-val you cannot use it 请记住,一旦移动l-val就无法使用它

For a bonus here is a resource that seems to explain the concept of r-val-refs and other concepts associated with them very well. 这里的奖励是一种资源 ,似乎可以很好地解释r-val-refs的概念以及与之相关的其他概念。

As others have suggested you could also switch to using emplace back since it actually perfect forwards the arguments to the constructor of the objects meaning you can pass it whatever you want. 正如其他人所建议你也可以切换到使用emplace,因为它实际上完美地将参数转发给对象的构造函数,这意味着你可以随意传递它。

  • When passing a parameter that's a forwarding reference , always use std::forward . 传递作为转发引用的参数时,请始终使用std::forward
  • When passing a parameter that's an r-value , use std::move . 传递一个r值的参数时,请使用std::move

Eg 例如

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

Here's an excellent video by Scott Meyers explaining forwarding references (which he calls universal references ) and when to use perfect forwarding and/or std::move : 以下是Scott Meyers的一段精彩视频,解释了转发引用(他称之为通用引用 )以及何时使用完美转发和/或std::move

C++ and Beyond 2012: Scott Meyers - Universal References in C++11 C ++和2012年之后:Scott Meyers - C ++中的通用引用11

Also see this related question for more info about using std::forward : Advantages of using forward 有关使用std::forward更多信息,请参阅此相关问题: 使用forward的优点

http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11

That video, IMO, has the best explanation of when to use std::forward and when to use std::move. 那个视频,IMO,有关何时使用std :: forward以及何时使用std :: move的最佳解释。 It presents the idea of a Universal Reference which is IMO an extremely useful tool for reasoning about move semantics. 它提出了通用参考的概念,这是IMO一个非常有用的推理移动语义的工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM