[英]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::bind
的cppreference文档说明绑定对象“持有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: 如果您不使用转发引用,则涉及三个对象:
f
, constructed using the copy or move constructor as appropriate 函数参数f
,根据需要使用复制或移动构造函数构造 If you use a forwarding reference with std::forward
, you eliminate the second one. 如果您使用带有std::forward
的转发引用,则会消除第二个引用。 There will only be two objects created: 只会创建两个对象:
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.