zoukankan      html  css  js  c++  java
  • 02--STL算法(函数对象和谓词)

    一:函数对象(仿函数):实现状态记录等其他操作<相对于普通函数>

    重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象。
    即是重载了“()”操作符的普通类对象。
    一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待。
    “在标准库中,函数对象被广泛地使用以获得弹性”,标准库中的很多算法都可以使用函数对象或者函数指针来作为自定的回调行为;
    一元函数对象:函数参数1个;
    
    二元函数对象:函数参数2个;

    (一)一元函数对象案例:实现数据显示

    普通函数调用:

    //普通函数
    template<typename T>
    void funcShow(T& t)
    {
        cout << t << endl;
    }
    
    int main()
    {
        int a = 100;
        funcShow<int>(a);
    }

    仿函数调用:

    //函数对象
    template<typename T>
    class classShow
    {
    public:
        int count;
    
        classShow()
        {
            count = 0;
        }
    
        void operator()(const T& t)
        {
            this->count++;    //状态记录
            cout << count<<"--->"<<t << endl;    //功能实现
        }
    };
    
    int main()
    {
        int a = 100;
        classShow<int> cs;    //函数对象
    
        cs(a);
        cs(a + 10);
        cs(a + 20);
    
    
        system("pause");
        return 0;
    }

    (二)二元函数对象案例:实现两个数相加

     仿函数实现:

    template<typename T>
    void ShowEle(const T& t)
    {
        cout << t << " ";
    }
    
    //仿函数
    template<typename T>
    struct SumAdd{    //C++中结构体可以实现类的相关操作
        T operator()(const T& t1,const T& t2)
        {
            return t1 + t2;
        }
    };
    
    int main()
    {
        vector<int> v1, v2,v3;
    
        for (int i = 0; i < 10; i++)
        {
            v1.push_back(rand() % 30);
            v2.push_back(rand() % 20);
        }
    
        for_each(v1.begin(), v1.end(), ShowEle<int>);
        cout << endl;
        for_each(v2.begin(), v2.end(), ShowEle<int>);
        cout << endl;
        v3.resize(10);    //需要提前分配好空间
        vector<int>::iterator iter = transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SumAdd<int>());
    
        for_each(v3.begin(), v3.end(), ShowEle<int>);
    
        system("pause");
        return 0;
    }

    二:谓词:实现过滤

    可以使用谓词来表示逻辑条件,用于描述对象持久性存储在内存中的对象过滤。其实意思就是:我是一个过滤器,不符合条件的都滚开。
    一元谓词函数参数1个,函数返回值是bool类型,可以作为一个判断式
    
    二元谓词函数参数2个,函数返回值是bool类型
    谓词可以使一个仿函数,也可以是一个回调函数。

    (一)一元谓词案例

    回调函数实现:判断string对象长度是否大于6

    bool GT6(const string& s)
    {
        return s.size() > 6;
    }

    仿函数实现:找出被某个数整除的所有元素

    template <typename T>
    class IsDiv
    {
    private:
        T divisor;
    public:
        IsDiv(const T& d)
        {
            this->divisor = d;
        }
    
        bool operator()(T& t)
        {
            return (t%divisor == 0);
        }
    };
    
    
    int main()
    {
        vector<int> v;
        
        for (int i = 4; i < 32; i++)
            v.push_back(i);
    
        IsDiv<int> isdiv(4);    //被4整除
        
        vector<int>::iterator iter;
    
        //返回找到符合条件的第一个
        iter = find_if(v.begin(), v.end(), isdiv);    //find_if(v.begin(), v.end(), IsDiv<int>(4));
        if (iter != v.end())
        {
            cout << "find first can divided by 4 is " << *iter << endl;
        }
        else
            cout << "can't find" << endl;
    
        system("pause");
        return 0;
    }

    (二)二元谓词案例

    回调函数实现:比较两个字符串,第一个字符串长度是否大于第二个

    bool isShorter(const string &s1, const string &s2)
    {
        return s1.size() < s2.size();
    }

    函数对象实现:实现按照二元谓词进行排序

    void printEle(int &v)    //遍历用
    {
        cout << v << " ";
    }
    
    template<typename T>
    class My_Sort_Desc
    {
    public:
        bool operator()(T& t1, T& t2)
        {
            return t1 > t2;
        }
    };
    
    int main()
    {
        vector<int> v;
        
        for (int i = 4; i < 32; i++)
            v.push_back(rand()%100);
    
        //打印元素
        for_each(v.begin(), v.end(), printEle);
        cout << endl;
        
        //进行排序
        sort(v.begin(), v.end(), My_Sort_Desc<int>());
    
        //打印元素
        for_each(v.begin(), v.end(), printEle);
    
        system("pause");
        return 0;
    }

    三:预定义函数对象

    (一)基本概念:标准模板库STL提前定义了很多预定义函数对象

    注意:要使用预定义函数对象必须引入#include <functional>

    (二)算数函数对象

    预定义的函数对象支持加、减、乘、除、求余和取反。调用的操作符是与type相关联的实例
    加法:plus<Types>
    
    减法:minus<Types>
    
    乘法:multiplies<Types>
    
    除法divides<Tpye>
    
    求余:modulus<Tpye>
    
    取反:negate<Type>
    plus<string> stringAdd;
    sres = stringAdd(sva1,sva2);  //加法函数对象使用
    
    negate<int> intNegate;
    ires = intNegate(ires);  //取反函数对象使用

    (三)关系函数对象

    等于equal_to<Tpye>
    
    不等于not_equal_to<Type>
    
    大于 greater<Type>
    
    大于等于greater_equal<Type>
    
    小于 less<Type>
    
    小于等于less_equal<Type>
    equal_to<string> stringEqual;  //等于函数对象使用
    sres = stringEqual(sval1,sval2);

    (四)逻辑函数对象

    逻辑与 logical_and<Type>
    
    逻辑或logical_or<Type>
    
    逻辑非logical_not<Type>
    logical_and<int> indAnd;
    ires = intAnd(ival1,ival2);  //逻辑与函数对象使用
  • 相关阅读:
    剑指Offer——对成的二叉树
    剑指Offer——二叉树的下一个节点
    路径总和I、II、III
    性能调优工具
    关于在程序中内存检测的一些知识
    ptmalloc、tcmalloc及 jemalloc总结
    [LeetCode] 43. 字符串相乘
    [LeetCode] 155. Min Stack
    [LeetCode] 380. Insert Delete GetRandom O(1)
    linux内存过高排查
  • 原文地址:https://www.cnblogs.com/ssyfj/p/10792767.html
Copyright © 2011-2022 走看看