STL-函数对象(仿函数)

简介: STL-函数对象(仿函数)

概念:

  • 重载函数调用操作符的类,其对象被称为函数对象
  • 函数对象使用重载的()时,行为类似函数调用,也叫仿函数

本质:

  • 函数对象(仿函数)是一个类,不是一个函数

函数对象使用:

  • 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
  • 函数对象超出普通函数的概念,函数对象可以有自己的状态
  • 函数对象可以作为参数传递
#include<iostream>
#include<string>
using namespace std;
//函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
class myAdd
{
public:
    int operator()(int v1, int v2)
    {
        return v1 + v2;
    }
};
void test1()
{
    myAdd a1;
    cout << a1(1, 2) << endl;
}
//函数对象超出普通函数的概念,函数对象可以有自己的状态
class myPrint
{
public:
    myPrint()
    {
        this->count = 0;
    }
    void operator()(string str)
    {
        cout << str << endl;
        count++;
    }
    int count;
};
void test2()
{
    myPrint p1;
    p1("A");
    p1("A");
    p1("A");
    cout << p1.count << endl;
}
//函数对象可以作为参数传递
void doPrint(myPrint& mp, string str)
{
    mp(str);
}
void test3()
{
    myPrint mp;
    doPrint(mp, "hello");
}
int main()
{
    test1();
    test2();
    test3();
    return 0;
}

谓词

  • 返回值是bool类型的仿函数被称为谓词
  • 如果operator()接受一个参数,那么叫做一元谓词
  • 如果operator()接受两个参数,那么叫做二元谓词

一元谓词举例

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class GreaterFive
{
public:
    bool operator()(int val)
    {
        return val > 5;
    }
};
int main()
{
    vector<int>v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    //查找容器中大于5的元素
    //GreaterFive() 匿名函数对象
    vector<int>::iterator it=find_if(v.begin(), v.end(), GreaterFive());
    cout << *it << endl;
    return 0;
}

二元谓词举例

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class myCompare
{
public:
    bool operator()(int v1, int v2)
    {
        return v1 > v2;
    }
};
int main()
{
    vector<int>v;
    v.push_back(10);
    v.push_back(30);
    v.push_back(20);
    v.push_back(40);
    //默认sort升序排序
    sort(v.begin(), v.end());
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
    sort(v.begin(), v.end(), myCompare());
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    return 0;
}

内建函数对象

STL内建了一些函数对象:

  • 算术仿函数
  • 关系仿函数
  • 逻辑仿函数

用法:

  • 这些仿函数所产生的对象,用法和一般函数完全相同
  • 使用内建仿函数,需要引入头文件<functional>

算术仿函数

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

  • template<class T> T puls<T>//加法
  • template<class T> T minus<T>//减法
  • template<class T> T multiplies<T>//乘法
  • template<class T> T modulus<T>//除法
  • template<class T> T negate<T>//取反
#include<iostream>
#include<functional>
using namespace std;
int main()
{
    //取反
    negate<int>n;
    cout << n(50) << endl;//-50
    cout << n(0) << endl;//0
    //加法 只填一个模板参数,默认相同类型
    plus<int>p;
    cout << p(10, 20) << endl;
    return 0;
}

关系仿函数

  • template<class T> bool equal_to<T>//等于
  • template<class T> bool not_equal_to<T>//不等于
  • template<class T> bool greater<T>//大于
  • template<class T> bool greater_equal<T>//大于等于
  • template<class T> bool less<T>//小于
  • template<class T> bool less_equal<T>//小于等于

sort默认的排序规则是从小到大,底层默认使用了less<T>

#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
int main()
{
    vector<int>v;
    v.push_back(10);
    v.push_back(30);
    v.push_back(40);
    v.push_back(20);
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << endl;
    }
    sort(v.begin(), v.end(), less<int>());
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << endl;
    }
    return 0;
}

逻辑仿函数

  • template<class T> bool logical_and<T>逻辑与
  • template<class T> bool logical_or<T>逻辑或
  • template<class T> bool logical_not<T>逻辑非
#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
int main()
{
    vector<bool>v;
    v.push_back(true);
    v.push_back(false);
    v.push_back(true);
    v.push_back(false);
    for (vector<bool>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
    //将容器v搬运到容器v1中,并执行取反操作
    vector<bool>v2;
    v2.resize(v.size());
    //注意没有 v2.end()
    transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());
    for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++)
    {
        cout << *it << " ";
    }
    return 0;
}
目录
相关文章
|
关系型数据库 MySQL
【MySQL】——Select查询语句知识点练习(其一)
【MySQL】——Select查询语句知识点练习(其一)
|
Kubernetes Java Maven
DHorse(K8S的CICD平台)的实现原理
首先,本篇文章所介绍的内容,已经有完整的实现,[可以参考这里](https://gitee.com/i512team/dhorse)。 在微服务、DevOps和云平台流行的当下,使用一个高效的持续集成工具也是一个非常重要的事情。虽然市面上目前已经存在了比较成熟的自动化构建工具,比如jekines,还有一些商业公司推出的自动化构建工具,但他们都不能够很好的和云环境相结合。那么[究竟该如何实现一个简单、快速的基于云环境的自动化构建系统呢](https://gitee.com/i512team/dhorse)?我们首先以一个Springboot应用为例来介绍一下整体的发布流程,然后再来看看具体如何实
|
开发工具 C语言 内存技术
ZYNQ_SDK HelloWorld实验
ZYNQ_SDK HelloWorld实验
|
11月前
|
机器学习/深度学习 自然语言处理 JavaScript
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
在信息论、机器学习和统计学领域中,KL散度(Kullback-Leibler散度)是量化概率分布差异的关键概念。本文深入探讨了KL散度及其相关概念,包括Jensen-Shannon散度和Renyi散度。KL散度用于衡量两个概率分布之间的差异,而Jensen-Shannon散度则提供了一种对称的度量方式。Renyi散度通过可调参数α,提供了更灵活的散度度量。这些概念不仅在理论研究中至关重要,在实际应用中也广泛用于数据压缩、变分自编码器、强化学习等领域。通过分析电子商务中的数据漂移实例,展示了这些散度指标在捕捉数据分布变化方面的独特优势,为企业提供了数据驱动的决策支持。
1228 2
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
|
7月前
|
人工智能 数据可视化 架构师
三句话生成 P5.js 粒子特效代码,人人都可以做交互式数字艺术
短短几分钟,两个完全不懂P5.js的人类,和通义灵码AI程序员一起,共同完成了有真实物理引擎和碰撞检测的3D仿真动画。人类扮演的角色更像产品经理和架构师,提出开发需求和迭代修改方案,而AI的作用更像码农,任劳任怨,熟练用各种编程语言完成技术底层的脏活累活。这只是AI编程的冰山一角,未来,每一个艺术家都能快速做出自己的创意原型,每一个数学老师都能轻松做出自己的教学动画。
|
编解码 算法 图形学
LabVIEW中调整图像大小
LabVIEW中调整图像大小
224 0
|
11月前
|
安全 算法 Java
强大!基于Spring Boot 3.3 六种策略识别上传文件类型
【10月更文挑战第1天】在Web开发中,文件上传是一个常见的功能需求。然而,如何确保上传的文件类型符合预期,防止恶意文件入侵,是开发者必须面对的挑战。本文将围绕“基于Spring Boot 3.3 六种策略识别上传文件类型”这一主题,分享一些工作学习中的技术干货,帮助大家提升文件上传的安全性和效率。
548 0
|
机器学习/深度学习 JSON 数据挖掘
使用Python调用API接口获取淘宝商品数据
本文介绍了如何使用Python调用API接口获取淘宝商品数据。通过调用淘宝开放平台的API接口,我们可以获取到淘宝商品的详细信息,包括商品名称、价格、销量等。这些数据可以用于进行各种分析,例如商品的价格趋势、销量趋势等。通过Python的强大功能,我们可以更方便地获取和处理这些数据,从而更好地理解淘宝的商品市场。
|
数据可视化 算法
时序分解 | MATLAB实现基于SVMD逐次变分模态分解的信号分解分量可视化
时序分解 | MATLAB实现基于SVMD逐次变分模态分解的信号分解分量可视化
|
监控 前端开发 数据可视化
数据可视化:内网流量监控软件的实时图表展示与HTML/CSS实现
在管理和监控内部网络流量时,数据可视化是一项至关重要的任务。它不仅可以帮助您更好地理解网络流量的趋势和模式,还可以及时发现潜在的问题。本文将介绍如何使用Ruby编写内网流量监控软件的扩展插件,以实现实时图表展示,同时提供自动提交监控数据到网站的解决方案。
513 0