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(); }
但是std :: bind语句没有通过引用绑定到f.调用func打印“100”而不是“1000”,这就是我想要的.
但是,如果我更改语句以获取指针它是否有效.
auto func = std::bind(&Foo::test,&f);
但这是通过我的理解通过指针传递f,并且我认为std :: bind采用r值参考Arg&& (如图here所示)这怎么工作?
有人可以解释一下吗?
解决方法
首先,std :: forward意味着用于perfect forwarding,即转发引用类型(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)); }
此外,您永远不应该在您之后需要访问某个状态的对象上使用std :: forward或std :: move.移动的对象被置于未指定但有效的状态,这基本上意味着除了销毁或重新分配状态之外,你不能对它们做任何事情.
通过引用std :: bind传递的参数?
函数std :: bind将始终复制或移动其参数.我找不到标准的适当引用,但en.cppreference.com says:
“The arguments to bind are copied or moved,and are never passed by reference unless wrapped in std::ref or std::cref.”
这意味着如果您将参数作为l值引用传递,则它是复制构造的,如果将其作为r值引用传递,则它将被移动构造.无论哪种方式,参数都不会作为参考传递.
为了避免这种情况你可以例如使用std::ref
作为可复制的引用包装器,它将在内部保持对调用站点的变量的引用.
auto func = std::bind(&Foo::test,std::ref(f));
或者您可以按照建议简单地将指针传递给f.
auto func = std::bind(&Foo::test,&f);
然后发生的是std :: bind将对从f上调用address-of运算符返回的临时指针的r值引用.此指针将被复制(因为指针无法移动)到std :: bind返回的绑定包装器对象中.即使指针本身被复制,它仍将指向调用站点上的对象,您将获得所需的引用语义.
或者使用lambda通过引用捕获f并调用函数Foo :: test.这是恕我直言的推荐方法,因为在一般情况下,lambdas比std :: bind表达式更通用,更强大.
Foo f; f.i = 100; auto func = [&f] { f.test(); }; f.i = 1000; func(); // 1000
注意:有关何时使用std :: forward的详细说明,请参阅this excellent video by Scott Meyers.