boost中bind的使用

Posted 学习时间轴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了boost中bind的使用相关的知识,希望对你有一定的参考价值。

 

1 Boost::bind

在介绍bind之前,我们先介绍一下STL中的绑定机制。我们知道在C++标准库中提供了bind1st,bind2nd函数绑定器和fun_ptr,mem_fun等函数适配器用来将函数绑定为一个函数对象。这些函数绑定器和适配器使用起来比较码分,需要根据全局函数还是类的成员函数,是一个参数还是多个参数等作出不同的选择,甚至有时候STL并不能满足我们的要求。boost库中提供的Boost::bind就是为了解决这个问题而设计的。

2 标准库中函数的绑定

我们首先看一下关于函数绑定是如何出现的。首先我们先看一下下面这个例子:

#include <iostream>
#include <vector>
#include <algorithm>
 
void print(int i)
{
    std::cout << i << std::endl;
}
 
int main()
{
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(2);
 
    std::for_each(v.begin(), v.end(), print);
}

这个例子很简单,就是依次遍历向量中的元素,并将其作为print的参数进行调用。在标准库中std::for_each()算法的第三个参数只能接受一个参数的函数或者函数对象。如果函数有多个参数,则上面的调用方法就行不通了,对应的解决方案是将函数定义为为函数对象,然后重载operator()的方法,最后利用标准库中的bind1st或者bind2nd来绑定重载运算的第一个参数或者第二个参数。
下面这个例子是将一个二元的相减的函数对象绑定为一个一元函数对象的例子,使用的是标准库中的std::bind1st

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
 
class sub :public std::binary_function<int, int, void>
{
public:
    void operator()(int i, int j) const
    {
        std::cout << i - j << std::endl;
    }
};
 
int main()
{
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(2);
 
    std::for_each(v.begin(), v.end(), std::bind1st(sub(),10));
}

被绑定的二元函数对象必须要继承std::binary_function,关于这个函数的使用可以参考 stl中std::binary_function的使用 。上面使用的是bind1st将10绑定到第一个参数上,即让10减去向量中的元素。如果想让向量减去10则使用bind2nd,关于标准库绑定的其他用法不是本文的重点这里就不过多介绍了。我们来看一下标准库这个用法的缺点,最明显的一个缺点就是需要改写函数为函数对象,因为在我们的应用中有些函数是允许我们进行修改的。另外一个缺点就是绑定的参数位置不同用的绑定方法也不同,达不到形式上的统一。看完下面介绍的boost::bind,你就会发现标准库的功能简直是太简陋了。

3 bind的工作原理

bind并不是一个单独的类或函数,而是非常庞大的家族,依据绑定的参数的个数和要绑定的调用对象的类型,共有数十种不同的形式,编译器会根据具体的绑定代码自动确定要使用的正确的形式,bind的基本形式如下:

template<class R,class F> bind(F f);
template<class R,class F,class A1>bind(F f,A1 a1);
 
namespace 
{
  boost::arg<1> _1;
  boost::arg<2> _2;