欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于std::bind

程序员文章站 2022-06-15 12:06:10
...

关于 std::bind

std::bind C++ 11 的一个新函数,返回值为一个函数对象,可以看作一个通用的函数适配器。它接受一个函数作为参数,并返回一个新的函数同时将一至多个参数绑定到返回的函数中。下文的内容包括如何使用bind 以及什么时候使用bind。

如何使用

假如我们已经有一个函数:

int add(int a, int b){
	return a + b;
}

bind将一个函数作为它的第一个参数,并将这个函数的参数作为自己的参数。在下面的代码中,newAddadd作为第一个参数,并且使用两个占位符来表示自己接受的参数。注意:_1, _2表示占位符,位于<functional>中,std::placeholders::_1;另外,由于普通函数做实参时会隐式转换成函数指针,因此&add 可以用 add 替代。

using namespace std::placeholders;	
auto newAdd = bind(&add, _1, _2);

在下面的代码中,5和6分别会与_1,_2 绑定,被add() 调用。因此 newAdd(5,6) 等价于 add(5, 6)

cout << newAdd(5, 6) << endl;	//11

我们也可以交换占位符,下面的代码中newAdd(5,6) 等价于 add(6,5) :

auto newAdd = bind(&add, _2, _1);
int result = newAdd(5,6);

现在,假设我们需要用bind()add() 写这样的一个函数:只接受一个整数 n,并且总是返回99+n的结果,则我们可以这样写:

auto newAdd = bind(&add, 99, _1);
int result = newAdd(12);			//111

在上面的代码中,_1 将会匹配到12,newAdd(12) 等价于add(99, 12)。 注意下面的代码也能正常通过编译的:

int res2 = newAdd(1, 2, 3, 4, 5);	//100

何时使用

由于 std::bind 返回的结果是一个函数对象,因此能很方便地使用在STL算法中。

假设现在我们有一个数组,我们需要统计数组中有多少个元素i满足i%5==0 , 并且使用已有的函数divisible(int num, int den);

bool divisible(int num , int den){
	if(num % den == 0)
		return true;
	return false;
}

若不使用bind() 我们可以这样写:

int main(){
	vector<int> ary{ 1, 20, 13, 4, 5, 6, 10, 28, 19, 15 };
	int count = 0;
	for (int &i : ary){
		if (divisible(i, 5)){
			count++;
		}
	}
	cout << count << endl;	//4
	return 0;
}

现在,我们使用bind() 和STL中的count_if()

//使用std::bind 和 counnt_if 解法
int main(){
	vector<int> ary{ 1, 20, 13, 4, 5, 6, 10, 28, 19, 15 };
	auto canDiv = bind(&divisible, _1, 5);
	int count = count_if(ary.begin(), ary.end(), canDiv);
	cout << count << endl;	//4
	return 0;
}

注意事项

std::bind返回值的类型是一个函数对象,上面的代码中,我们只是使用auto 来直接接收bind() 类型的返回值。但是我们也可以用std::function 来接受返回的对象, 例如:

function<int(int, int)> newAdd = bind(&add, _1, _2);