std::bind适配器的详解
std::bind 是 C++11 引入的函数适配器,位于头文件 <functional> 中。它可以将可调用对象(函数、函数指针、成员函数、函数对象等)与其部分参数绑定,生成一个新的可调用对象,这个新对象可以存储并在后续调用。它是传统 bind1st/bind2nd 的现代替代品,功能更强大且使用更灵活。
- 基本语法
- 可调用对象:可以是普通函数、函数指针、成员函数指针、函数对象(仿函数)等。
- 参数 :可以指定具体的值,也可以用占位符(
std::placeholders::_1,_2, ...)表示"将来调用时提供的参数"。 - 返回一个新的可调用对象,其类型为
std::bind返回的未指定类型(通常用auto或std::function保存)。 - 占位符 定义在
std::placeholders命名空间中,_1代表调用新对象时的第一个实参,_2代表第二个,依此类推。
c++
#include <functional>
auto bound_func = std::bind(可调用对象, 参数1, 参数2, ..., 参数N);
!注意\] 占位符的数量,必须等于"新函数对象需要接收的参数个数",否则会编译错误。
绑定普通函数
c++
using namespace std::placeholders;
// 1、绑定所有参数,生成一个无参可调用对象
auto bound_fun1 = bind(add, 100, 200);
int res = bound_fun1(); // 100 + 200 = 300
// 2、绑定部分参数
// // 第一个参数由调用时提供,第二个固定为100
auto bound_fun2 = bind(add, _1, 100);
res = bound_fun2(200); // 200 + 100 = 300
// 交换参数顺序
auto bond_fun3 = bind(add, _2, _1);
bond_fun3(100, 200); // 200 + 100 = 300
绑定仿函数
c++
template<typename T>
struct Multiply {
T operator()(T a, T b) {
return a * b;
}
};
int main()
{
using namespace std::placeholders;
vector<int> v = { 1, 2, 3, 4 };
// 两种绑定方式都可以
// Multiply<int> mult;
// auto bound_fun = bind(mult, _1, 10);
auto bound_fun = bind(Multiply<int>(), _1, 10);
for (int i : v) {
cout << bound_fun(i) << endl; // 10 20 30 40
}
return EXIT_SUCCESS;
};
绑定类成员函数
绑定类成员函数时,需注意:第一个参数必须是"类对象的地址"(&对象)或"类指针",后续参数为成员函数的参数(固定值/占位符)。
c++
class Person {
public:
void printName(string name, int age)
{
cout << "name = " << name << ",age = " << age << endl;
}
};
int main()
{
using namespace std::placeholders;
Person p;
// 第一个参数&p是类对象的指针
auto bound_fun1 = bind(&Person::printName, &p, _1, 25);
bound_fun1("张三"); // name = 张三,age = 25
return EXIT_SUCCESS;
};
使用注意事项
- 必须包含头文件
functional,否则会出现编译错误; - 占位符的使用:占位符的数量必须与"新函数对象需要接收的参数个数"一致;占位符的序号(_1、_2)必须与新函数调用时的参数顺序对应;
- 绑定类成员函数的注意点:必须传入类对象的地址(&对象)或类指针,否则无法调用成员函数;绑定const成员函数时,对象地址也需是const类型(若对象是const);
- bind返回的函数对象类型复杂,建议用auto接收,避免手动写类型;