C++ STL 函数对象

函数对象:

1.函数名

2.指向函数的指针

3.重载了()的类

函数名就是普通的函数,指向函数的指针会造成的一些问题是gdb、kdb的时候,调用栈会出现问题,因为这些调试工具跟踪的是函数名,用地址调用的时候符号表里面无法反应。使用重载了()的类对象的一个特点是可以使用额外的变量,例如构造对象的时候传入的私有成员数据。

函数符:

1.生成器:没有参数的函数符

2.一元函数:一个参数

3.二元参数:两个参数

谓词:返回bool值的一元函数

二元谓词:返回bool值的二元函数

使用重载了()的类的对象的一个好处是,需要调整值的时候,只要新创建一个对象就行而不用重新修改函数,例如,对于list的一个成员函数remove_if,参数是一个一元谓词,当返回值为true的时候,将节点删除,比如n > 100是条件,那么使用如下:

bool toobig(int n)
{
    if (n > 100)
        return true;
    return false;
}

list tmp;
tmp.remove_if(toobig);

下次若需要判断n > 200,就需要增加一个函数,若有频繁使用不同取舍值的场景,那么使用函数对象较好,每次创建新的对象就行了,如下:

template 
class TooBig
{
private:
    T cutoff;
public:
    TooBig(const T & t) : cutoff(t){}
    bool operator()(const T & t){return t > cutoff;}
};

listtmp;
tmp.remove_if(TooBig(10));

STL预定义函数符:头文件functional,是一些模板类对象,定义这些是为了防止对每种类型都定义一个同样功能的函数,比如double的加法和int的加法,可以直接用plus<>模板类,使用如下:

#include 
plusadd;
double tmp = add(1.1, 2.2);    //plus.operator()

所有内置算数运算符、关系运算符、逻辑运算符都有STL预定义的函数符

函数适配器:bind1st:用来制作适配器,将一个二元函数适配成一个一元函数,bind2nd用来替换的是第二个参数,如下:

void func2()
{
    double arr1[] = {28, 29, 30, 35, 38, 59};
    double arr2[] = {63, 65, 69, 75, 80, 99};
    vectorgr8(arr1, arr1 + 6);
    vectorm8(arr2, arr2 + 6);

    /* 5个参数的transform,使用二元函数 */
    vectorsum(6);
    transform(gr8.begin(), gr8.end(), m8.begin(), sum.begin(), plus());
    for_each(sum.begin(), sum.end(), show);
    cout << endl;

    /* 使用bind1st提供适配器,将二元函数转换为一元函数 */
    vectorprod(6);
    transform(gr8.begin(), gr8.end(), prod.begin(), bind1st(multiplies(), 2.5));
    for_each(prod.begin(), prod.end(), show);
    cout << endl;
}

C++11提供了lambda表达式,和python差不多

你可能感兴趣的:(cplusplus)