bind函数
根据一个可调用对象,生成一个新的可调用对象
int Add (int a, int b)
{
return a+b;
}
auto NewAdd = std::bind(Add, std::placeholders::_1, 4);
int res = NewAdd(3);//-->Add(3,4)
上面这段代码可以理解为,利用Add函数生成一个新的函数NewAdd,NewAdd的参数有一个,会在调用Add时候把参数放到_1的占位符的地方。
占位符
placeholders ,占位符。表示新的函数对象中参数的位置。当调用新的函数对象时,新函数对象会调用被调用函数,并且其参数会传递到被调用函数参数列表中持有与新函数对象中位置对应的占位符。
void function(arg1,arg2,arg3,arg4,arg5){};
auto g = bind(function,a,b,_2,c,_1);
//新的函数对象:g
//被调用函数:function
当调用函数对象g时候,函数对象g会调用function函数,并把其参数传给function函数,g的第一个参数会传给function的持有占位符_1的位置,即arg5。第二个参数会传给function的持有占位符_2的位置,即arg3。 其中的arg1,arg2,arg4已经被绑定到a,b,c上。
void g(X,Y);
//相对于调用下面函数
function(function,a,b,Y,c,X);
问题
假如是这样的:
#include <iostream>
#include <functional>
int func(int& a, int& b)
{
a = b + a;
b = a + b;
return a;
}
int main()
{
int a = 3;
int b = 4;
auto foo = bind(func, a, std::placeholders::_1);
std::cout<<foo(b)<<std::endl;
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
}
//out
7
3
11
可以看到生成的新函数并没有更新a的结果,为什么?因为bind函数是参数是传值的方式,也就是会拷贝一个临时变量,这样传入的就是一个临时变量,是一个右值(不过为啥运行没报错就不明白了),所以a的值没有更新,而placeholders其实是一个引用,也就是传入的是个指针,所以会改变。问题来了,如何解决?
- foo = bind(func, std::placeholders::_1, std::placeholders::_2); 每次调用时候这样写foo(a, x)就行
- auto foo = bind(func, std::ref(a), std::placeholders::_1);
其实这个std::ref比较好理解,唯一要理解的就是,bind和thread都是尼玛模板函数,所以当你传入引用的时候,就会调用引用构造函数,当bind传入的是一个引用类型,那么就会调用引用构造函数,所以底层接受的其实变成了指针而不再是临时对象了。在thread对象的初始化时候也会有同样的问题,解决方案一样。
版权声明:本文为feng__shuai原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。