谓词

谓词概念

概念:

  • 返回bool类型的仿函数 称为谓词

  • 如果operator()接受一个参数,那么叫做一元谓词

  • 如果operator()接受两个参数,那么叫做二元谓词

  • 带括号的是匿名类 不带括号的是函数指针(匿名构造函数,不需要将重载括号写后边, 内部逻辑自动补括号)mycompare()等同于mycompare m;

一元谓词

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
​
class diaoyong 
{
public:
    bool operator()(int a) 
    {
        return a > 5;  //这里控制条件
    }
};
​
void pushback(vector<int>&a) 
{
    int b;
    cout << "输入要插入的数量" << endl;
    cin >> b;
    for (int i = 0; i < b; i++) 
    {
        int c;
        cout << "输入要插入的数据" << endl;
        cin >> c;
        a.push_back(c);
    }
}
void fund(vector<int>&a)
{
    vector<int>::iterator it=find_if(a.begin(), a.end(), diaoyong());// diaoyong()匿名的函数对象 或者创建bool上的类的对象 写进去也可以 
    if (it == a.end())          //带括号的是匿名类 不带括号的是函数指针(匿名构造函数,不需要将重载括号写后边,   内部逻辑自动补括号)
    {
        cout << "未找到大于5的数字" << endl;
    }
    else 
    {
        cout << "找到了大于5的数字在"<<*it<< endl;
    }
}                                          
​
int main() 
{
    vector<int>a;
    pushback(a);
    fund(a);
    system("pause");
    return 0;
}
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
​
class diaoyong 
{
public:
    bool operator()(int a) 
    {
        return a > 5;  //这里控制条件
    }
};
​
class mycompare 
{
public:
    bool operator()(int a,int b) const 
    {
        return a > b;
    }
};
​
void pushback(vector<int>&a) 
{
    int b;
    cout << "输入要插入的数量" << endl;
    cin >> b;
    for (int i = 0; i < b; i++) 
    {
        int c;
        cout << "输入要插入的数据" << endl;
        cin >> c;
        a.push_back(c);
    }
    sort(a.begin(), a.end(), mycompare());//必须写在这里写别处 比如打印哪里跑不下来
}
/*void fund(vector<int>& a)
{
    vector<int>::iterator it=find_if(a.begin(), a.end(), diaoyong());// diaoyong()匿名的函数对象 或者创建bool上的类的对象 写进去也可以 
    if (it == a.end())          //带括号的是匿名类 不带括号的是函数指针(匿名构造函数,不需要将重载括号写后边,   内部逻辑自动补括号)
    {
        cout << "未找到大于5的数字" << endl;
    }
    else 
    {
        cout << "找到了大于5的数字在"<<*it<< endl;
    }
}                                          
*/
​
void printvector(vector<int> &a) 
{
    for (vector<int>::iterator it = a.begin(); it != a.end(); it++) 
    {
        cout << *it << endl;
    }
}
int main() 
{
    vector<int>a;
    pushback(a);
    //fund(a);
    printvector(a);
    system("pause");
    return 0;
}

内建函数对象

内建函数对象意义

概念:

  • STL内建了一些函数对象

分类:

  • 算术仿函数

  • 关系仿函数

  • 逻辑仿函数

用法:

  • 这些仿函数所产生的对象,用法和一般函数完全相同

  • 使用内建函数对象,需要引入头文件#include<functional>

算术仿函数

功能描述:

  • 实现四则运算

  • 其中negate是一元运算,其他都是二元运算

仿函数原型

 

#include<iostream>
#include<functional>
using namespace std;
​
int main() 
{
    int a;
    int b;
    cout << "输入要去相反数的数字" << endl;
    cin >> a;
​
    negate<int>d;
    cout << d(a) << endl;
    cout << "输入要相加的两数" << endl;
    int e;
    cout<<"输入第一个数"<<endl;
    cin >> b;
    cout << "输入第二个数" << endl;
    cin >> e;
    plus<int>c;
    cout << "和为" << c(b, e) << endl;
    system("pause");
    return 0;
}

关系仿函数

功能描述:

  • 实现关系对比

仿函数原型

 

#include<iostream>
//#include<algorithm>algorithm algorithm algorithm algorithm algorithm algorithm algorithm  algorithm  algorithm  algorithm  algorithm algorithm algorithm
#include<functional>
#include<vector>
#include<algorithm>
using namespace std;
​
int main() 
{
    /*int a;
    int b;
    cout << "输入要去相反数的数字" << endl;
    cin >> a;
​
    negate<int>d;
    cout << d(a) << endl;
    cout << "输入要相加的两数" << endl;
    int e;
    cout<<"输入第一个数"<<endl;
    cin >> b;
    cout << "输入第二个数" << endl;
    cin >> e;
    plus<int>c;
    cout << "和为" << c(b, e) << endl;
    */
    vector<int>a;
    int b;
    cout << "输入要存入的数据数" << endl;
    cin >> b;
​
    for (int i = 0; i < b; i++) 
    {
        int c;
        cout << "输入要存入的数据" << endl;
        cin >> c;
​
    }
    sort(a.begin(), a.end(), greater<int>());
    for (vector<int>::iterator it = a.begin(); it != a.end(); it++) 
    {
        cout << *it << endl;
    }
    system("pause");
    return 0;
}

逻辑仿函数

功能描述:

  • 实现逻辑运算

函数原型:

 



#include<iostream>
//#include<algorithm>algorithm algorithm algorithm algorithm algorithm algorithm algorithm  algorithm  algorithm  algorithm  algorithm algorithm algorithm
#include<functional>
#include<vector>
#include<algorithm>
using namespace std;
​
int main() 
{
    /*int a;
    int b;
    cout << "输入要去相反数的数字" << endl;
    cin >> a;
​
    negate<int>d;
    cout << d(a) << endl;
    cout << "输入要相加的两数" << endl;
    int e;
    cout<<"输入第一个数"<<endl;
    cin >> b;
    cout << "输入第二个数" << endl;
    cin >> e;
    plus<int>c;
    cout << "和为" << c(b, e) << endl;
    
​
​
    vector<int>a;
    int b;
    cout << "输入要存入的数据数" << endl;
    cin >> b;
​
    for (int i = 0; i < b; i++) 
    {
        int c;
        cout << "输入要存入的数据" << endl;
        cin >> c;
​
    }
    sort(a.begin(), a.end(), greater<int>());
    for (vector<int>::iterator it = a.begin(); it != a.end(); it++) 
    {
        cout << *it << endl;
    }*/
​
    vector<bool>a;
    int b;
    cout << "输入要存入的数据数" << endl;
    cin >> b;
​
    for (int i = 0; i < b; i++)
    {
        bool c;
        cout << "输入要存入的数据" << endl;
        cin >> c;
​
    }
    for (vector<bool>::iterator it = a.begin(); it != a.end(); it++)
    {
        cout << *it << endl;
    }
    cout << endl;
    cout << endl;
    vector<bool>s;
    s.resize(a.size());
    transform(a.begin(),a.end(), s.begin(), logical_not<bool>());//注意顺序不是以往的 开始位置 需要复制位置 是先需要复制位置后插入位置
    for (vector<bool>::iterator it = s.begin(); it != s.end(); it++)
    {
        cout << *it << endl;
    }
​
    system("pause");
    return 0;
}

仿函数的定义

  • 所谓仿函数(functor)就是使用起来像函数一样的东西。如果对某个class进行operator()重载,它就是一个仿函数类,该函数就是一个仿函数

  • 函数指针有缺点,最重要的是它无法持有自己的状态(局部状态),也无法达到组件技术中的可适配性(也就是无法再将来某些修饰徐条件加上,以达到改变其状态)。因此,STL算法的特殊版本所接受的所谓的”条件“或”策略“或”一整组操作“都是以仿函数呈现的

  • 函数对象是比函数更加通用的概念,因为函数对象可以定义跨越多次调用的可持久的部分(类似静态局部变量),同时又能从对象的外面进行初始化和检查(和静态局部变量不同)

  • 一个拥有应用操作符的函数对象可以被完美地内联化(inline),因为它没有涉及到任何指针,后者可能导致拒绝优化。与之形成对比的是,现有的优化器几乎不能(或者完全不能?)将一个通过函数指针的调用内联化。

    在标准库中,函数对象被广泛的使用以获得弹性

//仿函数类
template<class T>
struct Greater
{
    //仿函数
    bool operator()(const T& a, const T& b)
    {
        return a > b;
    }
};
void test()
{
    Greater<int> g;
    //原型
    bool ret = g.operator()(13, 14);
    cout << ret << endl;
    //简写形式-使用方法和函数类似
    ret = g(13, 14);
    cout << ret << endl;
}

1、函数对象——重载了()操作符的类

class SumAdd
{
public:
    void operator() ()  //这里两个括号看起来很怪,第一个是表示重载()操作符,第二个表示使用时()中写几个参数和参数的类型,这里没有写参数
    {
        
    }
};

2 、一元函数对象和二元函数对象

一元函数对象表示一个参数的函数对象(在类中重载()操作符时规定了一个参数),同理,二元函数对象就是两个参数的函数对象

//一元函数对象
class SumAdd
{
public:
    void operator() (int a) 
    {
        ...
    }
};
​
//二元函数对象
class SumAdd
{
public:
    void operator() (int a,int  b) 
    {
        ...
    }
};

那么有没有三元函数对象呢,按照这个规定,只要重载函数操作符时规定三个参数即可

3、函数对象的使用方法

当了解到函数对象怎么用市其实也很简单,定义一个重载了()的类的对象,然后直接使用()就行,就像用其他操作符一样(比如+ -等等) 具体例子

class myadd
{
public:
    int operator() (int &add1 , int &add2 ,int &add3)
    {
        return add1 + add2 + add3;
    }
};
int main(void)
{
    myadd myadd;    //用类定义一个对象
    int a = 6;
    int b = 8;
    int c = 8;
    int temp = myadd(a, b ,c);  //直接用()即可
    cout << "add:"<<temp << endl;
    cout << endl;
    system("pause")
}

4、伪函数

由上面例子可见,在重载了()操作符的对象使用()是,很像是在调用一个函数,所以函数对象也叫做伪函数,自己理解这个伪没有什么特殊的含义,就是指调用的样子和调用函数很像而已

5 、涉及函数对象的几个STL 算法

1、for_each()

class mycount
{
public:
    void operator()(int &count1)
    {
        n++;
        cout <<"void operator()(int &count1) n:"<< n << endl;
    }
    void printf_count()
    {
        cout << n << endl;
    }
public:
    int n;
};
​
int main(void)
{
    vector<int> v1;
    v1.push_back(1);
    v1.push_back(3);
    v1.push_back(5);mycount mycount;
for_each(v1.begin(), v1.end(), mycount); //匿名函数对象 匿名仿函数
cout << "mycount.n:"<<mycount.n << endl;//输出0
cout << "printf_count:";
mycount.printf_count();//输出0
​
mycount = for_each(v1.begin(), v1.end(), mycount); //匿名函数对象 匿名仿函数
cout << "2mycount.n:" << mycount.n << endl;//输出3
cout << "2printf_count:";
mycount.printf_count();//输出3
​
//for_each算法的 函数对象的传递 是元素值传递 ,不是引用传递
/*
    template<class _InIt,
    class _Fn1> inline
        _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
    {   // perform function for each element
        _DEBUG_RANGE(_First, _Last);
        _DEBUG_POINTER(_Func);
        return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func));
    }
*/
//分清楚 stl算法返回的值是迭代器 还是 谓词(函数对象)
cout << endl;
system("pause");

因为for_each()中函数对象的传递是值传递而不是引用传递,所以在传递的时候会为形参创建副本,所以改变的知识副本而已,要是想改变实参,就要知道函数返回的是什么,像for_each()返回的是一个对象,所以我们只要用原对象去接就行了 2、find_if()

class IsDiv
{
public:
    IsDiv(const int  &divisor)
    {
        this->divisor = divisor;
    }
    bool operator()(int  &t)
    {
        return (t%divisor == 0);
    }
private:
    int divisor;
};
int main(void)
{
    vector<int> v2;
    for (int i = 10; i<33; i++)
    {
        v2.push_back(i);
    }
    int a = 4;
    IsDiv myDiv(a);
    vector<int>::iterator it;
    it = find_if(v2.begin(), v2.end(), IsDiv(a));
    if (it == v2.end())
    {
        cout << "容器中没有被4整除的元素" << endl;
    }
    else
    {
        cout << "第一个是被4整除的元素是:" << *it << endl;
    }
}

ind_if()函数返回的则是一个迭代器,所以才说; !!!分清楚 stl算法返回的值是迭代器 还是 谓词(函数对象)

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐