C++小品:bind1st和bind2nd - [我的第一本C++书]


关于bind1st和bind2nd,这是两个在C++泛型(主要在STL、模板)很常用的两个函数,从这两个函数的名字就可以知道,他们的意义就是邦定(bind)某个函数的第一个参数(1st)或者第二个参数(2nd)。
我们常常在STL算法中应用函数指针或者函数对象对算法进行自己定义,例如,我们用一个printall()函数来对for_each()算法进行自定义,输出某个容器中的所有数据:
#include<iostream>
#include<algorithm>
#include<functional>
#include<vector>
using namespace std;
void printall(int n)
{
   cout<< "n = "<<n<<endl;
}

int main()
{

    int arr_v[] = {63,47,93,75};
    vector<int> v(arr_v,arr_v+4);


    // 打印容器中的全部数据

    for_each(v.begin(),v.end(),printall);

    return 0;

}



通过将函数指针printall转递给for_each算法,它就会以容器中的数据为参数调用这个函数,完成所有数据的输出。这是最简单的最常用的形式。

但是这种方式有一个缺点,就是不够通用灵活。例如,如我们想只是输出及格(>60)分数,我们就不得不另外写一个printpass函数来完成,而如果我们还有更多的变化,例如输出优秀(>85)、或者是差生的分数(<40),等等,情况有很多,采用这种方式,我们不得不为每一种情况实现一个专门的函数。这显然不符合泛型编程的思想(通用,一定要通用)。于是,bind1st和bind2nd也就派上了用场。

如果某个函数或函数对象调用需要两个参数,bind1st会邦定我们在调用bind1st的函数调用表达式中给出的参数为函数对象的第一个参数,而形成一个新的函数对象,也就是将一个二元(两个参数)函数对象的第一个参数固定下来,而形成一个新的只需要一个参数的一元函数对象,而将这个新的函数对象应用到算法时,相当于只有一个参数了(第一个参数已经被绑定),这时候情况就跟上面的例子完全相同了。例如:
void print(int standard,int n) // 创建一个需要两个参数的函数
{
    if(n>=standard)
        cout<< "n = "<<n<<endl;
}


int main()

{

    int arr_v[] = {63,47,93,75};
    vector<int> v(arr_v,arr_v+4);


// 打印容器中大于60的数据

for_each(v.begin(),v.end(),bind1st(ptr_fun(print),60)); // 这里,ptr_fun的作用是将一个函数指针构造成一个函数对象(你也可以直接使用函数对象),而bind1st就是帮定这个函数对象的第一个参数为60,也就是standard为60,整个函数变为print(60, int n),只有一个参数了,这是完全跟上面的例子相同了。

return 0;

}


bind2nd的原理是一样的,只不过是为了邦定函数的第二个参数。

而在新标准C++11中,还有bind函数,可以帮定更多参数。这些函数的使用是有点复杂,多加练习,熟悉后就好了。



猜你喜欢

转载自blog.csdn.net/DONGHUIB/article/details/52425957
今日推荐