🎖 博主的CSDN主页:Ryan.Alaskan Malamute
📜 博主的代码仓库主页 [ Gitee ]:@ryanala [GitHub]: Ryan-Ala
bind
bind也是一种函数包装器,也叫做适配器。它可以接受一个可调用对象,生成一个新的可调用对象来 “ 适应 ” 原对象的参数列表,C++中的bind本质是一个函数模板。
std::bind 函数定义在头文件 functional 中,是一个函数模板,它也有点像上面的包装器(适配器),接受一个可调用对象(函数/函数名、仿函数对象、lambda 表达式),然后生成一个新的可调用对象来“适应”原对象的参数列表。一般而言,我们用它可以把一个原本接收 N 个参数的可调用对象 Func,通过绑定一些参数,返回一个接收 M 个(通常 M <= N)参数的新函数。另外,使用 std::bind 模板还可以修改参数的传参顺序。
具体说的话,bind 可以去给可调用对象(通常是静态成员函数)参数列表中的参数指定缺省值,或者更改形参的接收顺序,然后生成一个新的可调用对象来“适应”原对象的参数列表。
bind函数模板的原型
头文件#include<functional>
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
带返回类型 (2)
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
模板参数说明:
fn
:可调用对象。args...
:要绑定的参数列表:值或占位符。
bind 包装器的用途
-
可以调整参数的顺序
int sub(int a,int b) { return a-b; } int main() { function<int(int,int)> f1 = Sub; cout<<f1(10,5)<<endl; //计算得出结果 5 using namespace std::placeholders; function<int(int,int)> f2 = bind(Sub,placeholders::_2,placeholders::_1); cout<<f2(10,5)<<endl; //计算的得出结果-5 //将Sub函数给bind包装器后,可以改变参数的顺序,但是需要用到 placeholders::_2 // 此时对应函数在调用时 第二个参数放到第一位置, }
-
调整参数个数
//调整参数个数 using namespace std::placeholders; function<int(int,int)> f2 = bind(Sub,20,placeholders::_1); cout<<f2(5)<<endl; //这里Sub函数的第一个操作数就为20,不变了 //可以使有些参数写死 using namespace std::placeholders; int main(void) { void confun(int a, int b, int c); auto con = bind(confun, 3, _2, _1); //第一个参数绑定指定的函数,后面的参数为绑定函数的参数列表 con(5,4); //之后可以这样调用原函数,且有些参数在绑定时给死 } void confun(int a,int b,int c) { cout << "a=" << a << ends << "b=" << b << ends << "c=" << c << endl; }
bind包装器的意义
- 将一个函数的某些参数绑定为固定的值,让我们在调用时可以不用传递某些参数。
- 可以对函数参数的顺序进行灵活调整。
其他使用示例
// bind example
#include <iostream> // std::cout
#include <functional> // std::bind
// a function: (also works with function object: std::divides<double> my_divide;)
double my_divide (double x, double y) {return x/y;}
struct MyPair {
double a,b;
double multiply() {return a*b;}
};
int main () {
using namespace std::placeholders; // adds visibility of _1, _2, _3,...
// binding functions:
auto fn_five = std::bind (my_divide,10,2); // returns 10/2
std::cout << fn_five() << '\n'; // 5
auto fn_half = std::bind (my_divide,_1,2); // returns x/2
std::cout << fn_half(10) << '\n'; // 5
auto fn_invert = std::bind (my_divide,_2,_1); // returns y/x
std::cout << fn_invert(10,2) << '\n'; // 0.2
auto fn_rounding = std::bind<int> (my_divide,_1,_2); // returns int(x/y)
std::cout << fn_rounding(10,3) << '\n'; // 3
MyPair ten_two {10,2};
// binding members:
auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply()
std::cout << bound_member_fn(ten_two) << '\n'; // 20
auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a
std::cout << bound_member_data() << '\n'; // 10
return 0;
}