简体   繁体   English

使用std :: forward而不是std :: move初始化对象有什么好处吗?

[英]Is there any benefit in using std::forward instead of std::move to initialize an object?

I have a function template that takes an argument of some callable type, and uses std::bind to make a new callable object with predefined argument values for the original callable. 我有一个函数模板,它接受一些可调用类型的参数,并使用std::bind创建一个新的可调用对象,其中包含原始可调用的预定义参数值。 I've written it with a forwarding reference parameter and std::forward , like this: 我用转发引用参数和std::forward编写了它,如下所示:

template <typename F>
auto make_example_caller(F &&f) {
  return std::bind(std::forward<F>(f), 123, 456, 789);
}

The cppreference documentation for std::bind says that the bound object "holds a member object of type std::decay<F>::type constructed from std::forward<F>(f) ". std::bindcppreference文档说明绑定对象“持有std::decay<F>::type的成员对象,从std::forward<F>(f)构造”。 Since std::bind forwards the function to its internal data member, forwarding the same function to the std::bind call in my own code seems reasonable and appropriate. 由于std::bind将函数转发给其内部数据成员,因此在我自己的代码中将相同的函数转发给std::bind调用似乎是合理和合适的。

However, it's not clear what benefit that brings. 但是,目前尚不清楚它带来了什么好处。 If F is a reference type, std::decay removes the reference, so the bind object is going to store its own instance of the callable type. 如果F是引用类型,则std::decay将删除引用,因此绑定对象将存储其自己的可调用类型实例。 That instance will be constructed as a move if F is an rvalue reference, or a copy if F is an lvalue, and I can get the same result if I write my function like this: 如果F是右值引用,那么该实例将被构造为移动,如果F是左值,则该实例将被构造为副本,如果我像这样编写我的函数,我可以获得相同的结果:

template <typename F>
auto make_example_caller(F f) {  // Note, no &&
  return std::bind(std::move(f), 123, 456, 789);  // move, not forward
}

Now my function's own f parameter will be initialized by either move or copy depending on how the function is called, but either way I now have my own instance of the function object, which I can move into the bind object. 现在我的函数自己的f参数将根据函数的调用方式通过移动或复制进行初始化,但无论哪种方式,我现在都有自己的函数对象实例,我可以将其移动到绑定对象中。

The latter way seems simpler, but I wonder if I'm missing something — especially since the same reasoning would apply to std::bind itself, yet it takes an F&& and forwards it, instead of taking an F by value and moving it. 后一种方式似乎更简单,但我想知道我是否遗漏了某些东西 - 特别是因为相同的推理将适用于std::bind本身,但它需要一个F&&并转发它,而不是取值F并移动它。 Is there a disadvantage in doing it that way? 这样做有不利之处吗? Something that I'm not seeing? 我没见过的东西?

Using a forwarding reference and std::forward you can eliminate the creation of an extra object. 使用转发引用和std::forward可以消除额外对象的创建。

If you don't use a forwarding reference, you have three objects involved: 如果您不使用转发引用,则涉及三个对象:

  1. Caller's original object 来电者的原始对象
  2. Function parameter f , constructed using the copy or move constructor as appropriate 函数参数f ,根据需要使用复制或移动构造函数构造
  3. Bind object's internal object, constructed by move constructor 绑定对象的内部对象,由移动构造函数构造

If you use a forwarding reference with std::forward , you eliminate the second one. 如果您使用带有std::forward的转发引用,则会消除第二个引用。 There will only be two objects created: 只会创建两个对象:

  1. Caller's original object 来电者的原始对象
  2. Bind object's internal object, constructed using the copy or move constructor as appropriate 绑定对象的内部对象,根据需要使用复制或移动构造函数构造

While move-constructing an object may be cheaper than copy-constructing (depending on the type), it still contributes some overhead that perfect-forwarding can avoid. 移动构造对象可能比复制构造(取决于类型)便宜,但它仍然会带来一些完美转发可以避免的开销。

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

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