• STL学习笔记(仿函数)


    仿函数(Functors)

    仿函数(functor),就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。

    例如我们定义一个类:

    class X{
        public:
            return-value operator()(arguments) const;
            ...  
    };

    然后就可以把这个类别的对象当做函数调用

    X fo;
    ...
    fo(arg1,arg2)  //等价于fo.operator()(arg1,arg2);

     显然,这种定义形式更为复杂,却又三大妙处:

    1.仿函数比一般函数更灵巧,因为它可以拥有状态。

    2.每个仿函数都有其型别。因此可以将仿函数的型别当做template参数传递。

    3.执行速度上,仿函数通常比函数指针更快。

    仿函数可当做排序准则

     1 #include <iostream>
     2 #include <string>
     3 #include <set>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 class Person{
     8     public:
     9         string firstname() const;
    10         string lastname() const;
    11         ...        
    12 };
    13 
    14 class PersonSortCriterion{
    15     public:
    16         bool operator()(const Person&p1,const Person& p2) const {
    17             return p1.lastname()<p2.lastname()||
    18                     (!(p2.lastname()<p1.lastname())&&
    19                     p1.firstname()<p2.firstname());
    20         }
    21 };
    22 
    23 int main()
    24 {
    25     typedef set<Person,PersonSortCriterion> PersonSet;
    26     PersonSet coll;
    27     PersonSet::iterator pos;
    28     for(pos=coll.begin();pos!=coll.end();++pos){
    29         ...
    30     }
    31     ...
    32 }
    View Code

    这里的coll适用了特殊排序准则PersonSortCritersion,而它是一个仿函数类别。所以可以当做set的template参数,而一般函数则无法做到这一点。

    拥有内部状态的仿函数

    下面例子展示仿函数如何模拟函数在同一时刻下拥有多个状态

     1 #include <iostream>
     2 #include <list>
     3 #include <algorithm>
     4 #include "print.cpp"
     5 using namespace std;
     6 
     7 class IntSequence
     8 {
     9 private:
    10     int value;
    11 public:
    12     IntSequence(int initialValue):value(initialValue){}
    13     int operator() ()
    14     {
    15         return value++;
    16     }
    17 };
    18 
    19 int main()
    20 {
    21     list<int> coll;
    22     generate_n(back_inserter(coll),9,IntSequence(1));
    23     PRINT_ELEMENTS(coll);
    24     generate(++coll.begin(),--coll.end(),IntSequence(42));
    25     PRINT_ELEMENTS(coll);
    26 }
    View Code

    for_each()的返回值

    使用for_each()可以返回其仿函数。下面将演示这一点

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 class MeanValue
     7 {
     8 private:
     9     long num;
    10     long sum;
    11 public:
    12     MeanValue():num(0),sum(0){}
    13     void operator() (int elem)
    14     {
    15         num++;
    16         sum+=elem;
    17     }
    18     double value()
    19     {
    20         return static_cast<double>(sum)/static_cast<double>(num);
    21     }
    22 };
    23 
    24 int main()
    25 {
    26     vector<int> coll;
    27     for(int i=1;i<=8;++i)
    28     {
    29         coll.push_back(i);
    30     }
    31     MeanValue mv=for_each(coll.begin(),coll.end(),MeanValue());
    32     cout<<"mean value:"<<mv.value()<<endl;
    33 }
    View Code

    预定义的仿函数

    C++标准程序库提供了许多预定义的仿函数。下面列出了所有这些仿函数

    对对象排序或进行比较时,一般都以less<>为预设排序准则。要使用这些仿函数,必须包含头文件<functional>。

    函数配接器(Function Adapters)

    所谓“函数配接器”是指能够将仿函数和另一个仿函数(或某个值,或一般函数)结合起来的仿函数。函数配接器也声明与<functional>中。

    例如以下语句:

    find_if(coll.begin(),coll.end(),bind2nd(greater<int>()),42)

    其中bind2nd是将一个二元仿函数(greater<>)转换成一元仿函数。它通常将第二参数传给“由第一参数指出”的二元仿函数,作为后者的第二参数。

    下面列出了预定义的函数配接器

  • 相关阅读:
    移植Valgrind检测Android JNI内存泄漏
    【转】线性回归最小二乘法和梯度下降法
    【转】成为一名推荐系统工程师永远都不晚
    vue-element-admin使用常见问题
    SpringBoot中如何使用jpa和jpa的相关知识总结
    SpringBoot Controller接收参数的几种常用方式
    java项目其他基础配置
    eclipse 新建 maven 项目 + 消除错误
    vue城市三级联动组件 vue-area-linkage
    Vue中watch的简单应用
  • 原文地址:https://www.cnblogs.com/runnyu/p/4840489.html
Copyright © 2020-2023  润新知