我有以下代码将成员函数绑定到类的实例:
class Foo {
public:
int i;
void test() {
std::cout << i << std::endl;
}
};
int main() {
Foo f;
f.i = 100;
auto func = std::bind(&Foo::test, std::forward<Foo>(f));
f.i = 1000;
func();
}
Run Code Online (Sandbox Code Playgroud)
但该std::bind
声明并未f
通过引用绑定.调用func
打印"100"而不是"1000"这是我想要的.
但是,如果我更改语句以获取指针它是否有效.
auto func = std::bind(&Foo::test, &f);
Run Code Online (Sandbox Code Playgroud)
但是,这是通过f
由指针我的理解,因为我认为std::bind
需要一个R值的参考Arg&&
(如图所示这里)如何工作的呢?
有人可以解释一下吗?
Snp*_*nps 19
std::forward
首先,std::forward
意味着用于完美转发,即转发引用类型(l值或r值).
如果将l值引用传递给std::forward
返回的值,同样如果传递了r 值引用,则返回r值.与此相反std::move
,它将始终返回r值引用.还要记住,命名的 r值引用是l值引用.
/* 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));
}
Run Code Online (Sandbox Code Playgroud)
此外,您永远不应该使用std::forward
或std::move
在您之后需要访问某个状态的对象上.移动的对象被置于未指定但有效的状态,这基本上意味着除了销毁或重新分配状态之外,您无法对它们执行任何操作.
std::bind
?该函数std::bind
将始终复制或移动其参数.我无法从标准中找到合适的引文,但en.cppreference.com说:
"绑定的参数被复制或移动,除非包含在std :: ref或std :: cref中,否则永远不会通过引用传递."
这意味着如果将参数作为l值引用传递,则它是复制构造的,如果将其作为r值引用传递,则它是移动构造的.无论哪种方式,参数都不会作为参考传递.
为了避免这种情况,你可以使用std::ref
例如一个可复制的引用包装器,它将在内部保持对调用站点变量的引用.
auto func = std::bind(&Foo::test, std::ref(f));
Run Code Online (Sandbox Code Playgroud)
或者您可以f
按照建议简单地传递指针.
auto func = std::bind(&Foo::test, &f);
Run Code Online (Sandbox Code Playgroud)
然后std::bind
会发生什么,它将对从调用address-of运算符返回的临时指针进行r值引用f
.此指针将被复制(因为指针无法移动)到从中返回的绑定包装器对象中std::bind
.即使指针本身被复制,它仍将指向调用站点上的对象,您将获得所需的引用语义.
或者使用通过引用捕获的lambdaf
并调用该函数Foo::test
.这是恕我直言的推荐方法,因为lambdas比std::bind
一般情况下的表达更通用和更强大.
Foo f;
f.i = 100;
auto func = [&f] { f.test(); };
f.i = 1000;
func(); // 1000
Run Code Online (Sandbox Code Playgroud)
注意:有关何时使用的详细说明,std::forward
请参阅Scott Meyers的精彩视频.
所采用的参数std::bind
实际上是通用引用,它可以绑定到左值和右值.你不能只传递值std::bind
,因为那会复制它.
要将引用传递给std::bind
您可以使用std::ref
:
auto func = std::bind(&Foo::test, std::ref(f));
Run Code Online (Sandbox Code Playgroud)