zoukankan      html  css  js  c++  java
  • 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<>)转换成一元仿函数。它通常将第二参数传给“由第一参数指出”的二元仿函数,作为后者的第二参数。

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

  • 相关阅读:
    JavaScript——标准对象
    JavaScript——方法
    JavaScript——变量作用域
    移动开发程序员的悲哀是什么?
    腾讯14年老员工被公司恶意逼走!以不胜任工作为由被裁!腾讯对待老员工也太狠了吧?
    Android开发北漂 8 年,飘飘飘 飘够了。。。。
    我是双非/三本/专科学校的Android开发,我有机会进入大厂吗?
    Android开发3年,我转Java后台了,真香!
    我的字节跳动Android面试初体验——稀里糊涂结束战斗
    Android Studio 教程:入门开发第一个程序
  • 原文地址:https://www.cnblogs.com/runnyu/p/4840489.html
Copyright © 2011-2022 走看看