使用注意事项std::forward
首先,std::forward
意味着用于完美转发,即转发引用类型(左值或右值)。
如果您传递一个左值引用std::forward
,则返回该值,同样,如果传递一个右值引用,则返回一个右值。这与std::move
始终返回 r 值引用相反。还要记住命名的右值引用是左值引用。
/* Function that takes r-value reference. */
void func(my_type&& t) {
// 't' is named and thus is an l-value reference here.
// Pass 't' as lvalue reference.
some_other_func(t);
// Pass 't' as rvalue reference (forwards rvalueness).
some_other_func(std::forward<my_type>(t));
// 'std::move' should be used instead as we know 't' is always an rvalue.
// e.g. some_other_func(std::move(t));
}
此外,您永远不应该使用std::forward
或std::move
在您之后需要从中访问某些状态的对象上。被移动的对象被置于一个未指定但有效的状态,这基本上意味着你不能对它们做任何事情,除了销毁或重新分配一个状态给它们。
通过引用传递的参数std::bind
?
该函数std::bind
将始终复制或移动其参数。我无法从标准中找到适当的引用,但en.cppreference.com 说:
“绑定的参数被复制或移动,并且永远不会通过引用传递,除非包装在 std::ref 或 std::cref 中。”
这意味着如果您将参数作为左值引用传递,那么它是复制构造的,如果您将它作为右值引用传递,那么它是移动构造的。无论哪种方式,参数都永远不会作为引用传递。
为了规避这种情况,您可以例如std::ref
用作可复制的引用包装器,它将在内部保留对调用站点变量的引用。
auto func = std::bind(&Foo::test, std::ref(f));
或者您可以f
按照您的建议简单地传递一个指针。
auto func = std::bind(&Foo::test, &f);
然后std::bind
会发生 r-value 引用到从调用 address-of 运算符返回的临时指针 on f
。该指针将被复制(因为指针无法移动)到从std::bind
. 即使指针本身被复制,它仍将指向调用站点的对象,您将获得所需的引用语义。
或者使用通过引用捕获并调用函数的lambda。恕我直言,这是推荐的方法,因为 lambda在一般情况下比表达式更加通用和强大。f
Foo::test
std::bind
Foo f;
f.i = 100;
auto func = [&f] { f.test(); };
f.i = 1000;
func(); // 1000
注意:有关何时使用的详细说明,std::forward
请参阅Scott Meyers 制作的精彩视频。