C++STL 仿函数

1. 概述
仿函数(functors)是早期的命名,C++标准规格定案后采用的新名称是函数对象(function objects)(也就是一种具有函数特质的对象)。

仿函数的作用:

在C++的STL提供的各种算法,例如sort()。往往有两个版本,其中一个是最长用的某种运算的版本(operator<);第二个版本则表现出最泛化的演算流程,允许用户“以template参数来指定所需要采取的策略”。

仿函数产生的原因:

由于函数指针毕竟不能满足STL对抽象对象的需求,也不能满足软件积木的需求——函数指针无法和STL其它组件(如配接器adapter)搭配使用,产生更灵活的变化。

2. 编码
2.1 仿函数实现示例

//仿函数1,比较大小
template<typename T> struct comp
{
    bool operator()(T in1, T in2) const
    {
        return (in1>in2);
    }
};
 
comp<int> m_comp_objext;
cout << m_comp_objext(6, 3) << endl;     //使用对象调用
cout << comp<int>()(1, 2) << endl;       //使用仿函数实现
在上面的代码中,第一种调用方式是使用comp的定义的一个对象,然后通过这个对象来调用操作符(),来实现两个数组的比较的;对于第二个调用comp<int>()(1, 2)是产生一个临时(无名的)对象。
2.2 仿函数详细说明
在下面的使用场景(统计一个容器中的符合规定的元素),将说明之前提到的函数指针为什么不能在STL中替换掉仿函数


bool my_count(int num)
{
    return (num < 5);
}
 
int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> v_a(a, a+10);
cout << "count: " << std::count_if(v_a.begin(), v_a.end(), my_count);
在上面我们传递进去了一个函数指针作为count_if的比较条件。但是现在根据新的需求,不再统计容器中小于5的变量个数,改为了8或者3。那么最直接的方法就是加一个参数threshold就可以了,就像下面这样
bool my_count(int num, int threshold)
{
    return (num < threshold));
}
但是这样的写法STL中是不能使用的,而且当容器中的元素类型发生变化的时候就不能使用了,更要命的是不能使用模板函数。
那么,既然多传递传递参数不能使用,那就把需要传递进来的那个参数设置为全局的变量,那样确实能够实现当前情况下对阈值条件的修改,但是修改起来存在隐患(要是没有初始化就调用怎么办)。因而解决这样问题的方式就是仿函数

template<typename T> struct my_count1
{
    my_count1(T a)
    {
        threshold = a;
    }
    T threshold;
    bool operator()(T num)
    {
        return (num < threshold);
    }
};
 
int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> v_a(a, a+10);
 
cout << "count: " << std::count_if(v_a.begin(), v_a.end(), my_count1<int>(8));
这样的方式就很好的兼容了STL。
 

猜你喜欢

转载自blog.csdn.net/pql925/article/details/83210728