浅谈STL|STL函数对象篇

一.函数对象概念
概念:
·重载函数调用操作符的类,其对象常称为函数对象
·函数对象使用重载的()时,行为类似函数调用,也叫仿函数
本质:
函数对象(仿函数)是一个类,不是一个函数
特点
- 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值;
- 函数对象超出普通函数的概念,函数对象可以有自己的状态;
- 函数对象可以作为参数传递;
函数对象可以像普通函数一样被调用,并且可以接受参数和返回值。通过重载函数调用操作符 operator(),函数对象可以在使用时表现得像函数一样。
函数对象的一个优势是它可以拥有自己的状态。由于函数对象实际上是一个类的对象,所以它可以拥有成员变量,这些变量可以在每次调用时保持状态并进行更新。这使得函数对象可以在多次调用之间维护一些信息。
此外,函数对象还可以作为参数传递给其他函数。许多标准库的算法函数,例如 std::sort、std::transform 等,可以接受函数对象作为参数,以定义算法的具体操作。通过将函数对象传递给其他函数,我们可以实现更灵活、可定制的功能。
以下是一个简单的示例,展示了函数对象的用法:
#include <iostream>class MyFunctor
{
public:void operator()(int x) const{// 在回调时输出消息std::cout << "Function object called with " << x << std::endl;}
};void callWithFunctor(const MyFunctor& functor, int value)
{functor(value); // 调用函数对象
}int main()
{MyFunctor functor;callWithFunctor(functor, 42); // 传递函数对象给函数,并进行调用return 0;
}
在上述示例中,MyFunctor 是一个函数对象,我们将它作为参数传递给 callWithFunctor 函数,并在函数内部调用函数对象。
总结来说,函数对象可以像普通函数一样被调用,可以接受参数和返回值,可以拥有自己的状态,并可以作为参数传递给其他函数,这使得函数对象在编程中非常有用和灵活。
函数对象相比于普通函数具有一个重要的优势,那就是函数对象可以拥有自己的状态。这意味着函数对象可以在多次调用之间记录和维护自己的内部数据。
普通函数是无状态的,它们不会保留任何关于之前调用的信息。每次调用函数时,它们只是根据传入的参数执行相应的操作,并返回结果。
而函数对象则可以在每次调用时保持状态,并根据状态的变化来改变行为。这种状态是通过函数对象的成员变量来实现的。函数对象的成员变量可以记录在调用过程中需要持久化的数据,而这些数据会在不同的函数调用之间持续存在。
这种函数对象的状态可以非常有用。它允许我们在不同的调用之间共享和利用数据,从而实现更复杂的行为。例如,我们可以使用函数对象来实现一个计数器,每次调用增加计数值,并在后续的调用中使用该值。
以下是一个简单的示例,展示了函数对象中保存状态的功能:
#include <iostream>class Counter
{
public:Counter() : count(0) {}int operator()(){return ++count;}private:int count;
};int main()
{Counter counter;std::cout << counter() << std::endl; // 输出:1std::cout << counter() << std::endl; // 输出:2std::cout << counter() << std::endl; // 输出:3return 0;
}
在上述示例中,Counter 是一个函数对象,它通过重载函数调用操作符 operator() 来实现计数的功能。每次调用 Counter 对象时,计数器的值会增加,并返回新的计数值。
总结而言,函数对象相比普通函数具有自己的状态,这使得它们可以在多次调用之间保持数据,并根据状态的变化改变行为。这种功能使得函数对象在许多应用场景中非常有用,例如实现计数器、缓存等。
二.谓词
概念:
- 返回bool类型的仿函数称为谓词
- 如果operator()接受一个参数,那么叫做一元谓词
- 如果operator()接受两个参数,那么叫做二元谓词
返回 bool 类型的仿函数被称为谓词(Predicate)。谓词通常用于对某些条件进行判断,并返回相应的布尔值。
此外,根据 operator() 接受的参数数量,可以将谓词进一步分类为一元谓词(Unary Predicate)和二元谓词(Binary Predicate)。
- 一元谓词是指
operator()只接受一个参数的谓词。它用于对单个对象进行判断,返回一个布尔值。一元谓词通常用于像std::find_if、std::remove_if等算法中。 - 二元谓词是指
operator()接受两个参数的谓词。它用于对两个对象进行比较或判断,返回一个布尔值。二元谓词通常用于像std::sort、std::find等算法中,用于指定排序规则或比较条件。
通过使用谓词,我们可以灵活地对对象进行条件判断和过滤。
以下是一个简单的示例,展示了一元谓词和二元谓词的概念:
#include <iostream>
#include <vector>
#include <algorithm>// 一元谓词
struct IsEven
{bool operator()(int n) const{return n % 2 == 0;}
};// 二元谓词
struct IsLess
{bool operator()(int a, int b) const{return a < b;}
};int main()
{std::vector<int> numbers = { 1, 2, 3, 4, 5 };// 使用一元谓词查找第一个偶数auto it = std::find_if(numbers.begin(), numbers.end(), IsEven());if (it != numbers.end()){std::cout << "First even number: " << *it << std::endl;}// 使用二元谓词排序std::sort(numbers.begin(), numbers.end(), IsLess());// 输出排序结果std::cout << "Sorted numbers: ";for (int num : numbers){std::cout << num << " ";}std::cout << std::endl;return 0;
}
在上述示例中,IsEven 是一个一元谓词,通过重载 operator() 来判断一个数字是否为偶数。IsLess 是一个二元谓词,通过重载 operator() 实现了两个数字的比较操作。
我们在主函数中使用了一元谓词来查找第一个偶数,并使用二元谓词对数组进行排序。
总结来说,返回 bool 类型的函数对象被称为谓词。根据 operator() 接受的参数数量,谓词可以进一步分类为一元谓词和二元谓词。谓词在标准库的算法中大量使用,用于自定义比较和条件判断。
find_if
、std::find_if 是 C++ 标准库中的一个算法函数,它的作用是在给定的范围内查找满足指定条件的元素,并返回第一个满足条件的元素的迭代器。
函数签名如下所示:
template <class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p);
参数说明:
first和last:表示要查找的元素范围,first表示范围的起始位置,last表示范围的结束位置(不包含在范围内)。p:一个一元谓词,用于判断元素是否满足条件。
函数返回值是一个迭代器,指向范围内第一个满足条件的元素,如果没有找到满足条件的元素,则返回 last。
以下是一个简单的示例,展示了 std::find_if 的使用:
#include <iostream>
#include <vector>
#include <algorithm>struct IsEven
{bool operator()(int n) const{return n % 2 == 0;}
};int main()
{std::vector<int> numbers = { 1, 2, 3, 4, 5 };// 使用一元谓词查找第一个偶数auto it = std::find_if(numbers.begin(), numbers.end(), IsEven());if (it != numbers.end()){std::cout << "First even number: " << *it << std::endl;}return 0;
}
在上述示例中,我们定义了一个一元谓词 IsEven,用于判断一个数字是否为偶数。然后,我们使用 std::find_if 函数在 numbers 容器中查找第一个满足条件的偶数,并输出结果。
值得注意的是,std::find_if 在查找到满足条件的元素后,会立即停止搜索并返回该元素的迭代器。如果要查找出多个满足条件的元素,可以使用 std::find_if 结合其他算法函数或循环进行迭代查找。
三.内建函数对象
当涉及到内建函数对象时,可以根据它们的功能将它们分为三类: 算术函数对象、逻辑函数对象和关系函数对象。
-
算术函数对象:
- std::plus: 加法操作。
- std::minus: 减法操作。
- std::multiplies: 乘法操作。
- std::divides: 除法操作。
- std::modulus: 取模操作。
-
逻辑函数对象:
- std::logical_and: 逻辑与操作。
- std::logical_or: 逻辑或操作。
- std::logical_not: 逻辑非操作。
-
关系函数对象:
- std::less: 小于比较。
- std::less_equal: 小于等于比较。
- std::greater: 大于比较。
- std::greater_equal: 大于等于比较。
- std::equal_to: 等于比较。
- std::not_equal_to: 不等于比较。
这些函数对象可以通过重载 operator() 来执行特定的操作或比较,它们被设计为与标准库算法一起使用,以提供通用的功能。通过使用这些函数对象,我们可以以一种通用且灵活的方式处理算术、逻辑和关系操作。
当涉及到内建函数对象时,我们可以通过以下示例来展示它们的使用:
- 算术函数对象:
#include <iostream>
#include <functional>int main() {std::plus<int> add;int a = 5, b = 10;int result = add(a, b);std::cout << "Addition result: " << result << std::endl; // 输出:15return 0;
}
在上述示例中,我们使用了 std::plus 函数对象来执行加法操作,将数字 a 和 b 相加,并将结果存储在 result 变量中。
- 逻辑函数对象:
#include <iostream>
#include <functional>int main() {std::logical_and<bool> logicAnd;bool value1 = true, value2 = false;bool result = logicAnd(value1, value2);std::cout << "Logical AND result: " << std::boolalpha << result << std::endl; // 输出:falsereturn 0;
}
在上述示例中,我们使用了 std::logical_and 函数对象来执行逻辑与操作,对 value1 和 value2 进行逻辑与运算,并将结果存储在 result 变量中。
- 关系函数对象:
#include <iostream>
#include <functional>int main() {std::less<int> lessThan;int a = 5, b = 10;bool result = lessThan(a, b);std::cout << "Less than result: " << std::boolalpha << result << std::endl; // 输出:truereturn 0;
}
在上述示例中,我们使用了 std::less 函数对象来执行小于比较,判断 a 是否小于 b,并将结果存储在 result 变量中。
这些示例演示了如何使用内建函数对象进行算术、逻辑和关系操作。您可以通过实例化适当的函数对象类模板,然后将其用作函数调用,以便执行所需的操作或比较。
请注意,这些示例可能只是演示了函数对象的一小部分用法,这些函数对象在标准库的算法和其他使用场景中非常有用。
好的,下面是一个整理成表格的例子,展示了内建函数对象及其用途的示例。
| 函数对象 | 用途 | 示例 |
|---|---|---|
| std::plus | 加法操作 | std::plus()(2, 3) // 输出:5 |
| std::minus | 减法操作 | std::minus()(5, 2) // 输出:3 |
| std::multiplies | 乘法操作 | std::multiplies()(3, 4) // 输出:12 |
| std::divides | 除法操作 | std::divides()(10, 2) // 输出:5 |
| std::modulus | 取模操作 | std::modulus()(10, 3) // 输出:1 |
| std::logical_and | 逻辑与操作 | std::logical_and()(true, false) // 输出:false |
| std::logical_or | 逻辑或操作 | std::logical_or()(true, false) // 输出:true |
| std::logical_not | 逻辑非操作 | std::logical_not()(true) // 输出:false |
| std::less | 小于比较 | std::less()(2, 5) // 输出:true |
| std::less_equal | 小于等于比较 | std::less_equal()(5, 5) // 输出:true |
| std::greater | 大于比较 | std::greater()(5, 2) // 输出:true |
| std::greater_equal | 大于等于比较 | std::greater_equal()(5, 5) // 输出:true |
| std::equal_to | 相等比较 | std::equal_to()(2, 2) // 输出:true |
| std::not_equal_to | 不等比较 | std::not_equal_to()(2, 5) // 输出:true |
相关文章:
浅谈STL|STL函数对象篇
一.函数对象概念 概念: 重载函数调用操作符的类,其对象常称为函数对象 函数对象使用重载的()时,行为类似函数调用,也叫仿函数 本质: 函数对象(仿函数)是一个类,不是一个函数 特点 函数对象在使用时,可以像普通函数那…...
自建私人图床方案:使用Cpolar+树洞外链轻松部署超轻量级图床,实现高效图片存储
文章目录 1.前言2. 树洞外链网站搭建2.1. 树洞外链下载和安装2.2 树洞外链网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道(云端设置)3.3 Cpolar稳定隧道(本地设置) 4.公网访问测试5.结语…...
从零基础到精通Flutter开发:一步步打造跨平台应用
💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 导言 Flutter是一种流行…...
SpringBoot整合WebSocket【代码】
系列文章目录 一、SpringBoot连接MySQL数据库实例【tk.mybatis连接mysql数据库】 二、SpringBoot连接Redis与Redisson【代码】 三、SpringBoot整合WebSocket【代码】 四、SpringBoot整合ElasticEearch【代码示例】 文章目录 系列文章目录代码下载地址一、效果演示二、引入依赖…...
微服务 第一章 Java线程池技术应用
系列文章目录 第一章 Java线程池技术应用 文章目录 系列文章目录[TOC](文章目录) 前言1、Java创建线程方式回顾1.1、继承Thread类(只运行一次)1.1.1、改造成主线程常驻,每秒开启新线程运行1.1.2、匿名内部类1.1.3、缺点1.1.4、扩展知识:Java内部类1.1.4…...
行业追踪,2023-09-14
自动复盘 2023-09-14 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...
传输层协议--UDP
引入 传输层负责数据能够从发送端传输到接收端。 端口号(Port) 端口号标识了一个主机上进行通信的一个进程。 两个问题: 1. 一个进程可以绑定多个端口号吗?--可以 2.一个端口号可以绑定多个进程吗?--不可以 我们…...
微信会员卡开发流程
功能需求: 通过微信第三方平台创建的模板小程序,想要实现用户在小程序支付一定金额后领取会员卡,领取会员卡后可给用户下发一定数量的优惠券,并且实现用户在小程序消费享受商品折扣。 开发流程: 一、了解微信的3个平…...
《算法竞赛·快冲300题》每日一题:“点灯游戏”
《算法竞赛快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 点…...
常见高级语言的输入与输出训练(一)
文章目录 题目概述1 输入描述: 输出描述: 输入 输出 示例C语言代码 题目概述2 题目描述 输入描述: 输出描述: 输入 输出 示例Java代码 前言 本文主要讲解两个算法题的代码实现 题目概述1 计算ab 打开以下链接可以查看正确的代码 数据范围:数据组数满…...
恭喜!龙蜥获得 2023 大学生操作系统设计赛二等奖及特殊贡献奖
经过多月的激烈角逐,2023 全国大学生系统能力大赛操作系统设计赛(以下简称“2023 大学生操作系统赛”) 圆满结束。经过 2023 大学生操作系统赛评审组和技术委员会的复核,面向全国公布了此次大赛的获奖名单。龙蜥社区不负众望&…...
中项系统集成项目管理2023上半年真题及解析
中项系统集成项目管理2023上半年真题及解析 上午题1. 在 (1) 领域,我国还远未达到世界先进水平,需要发挥新型举国体制优势,集中政府和市场两方面的力量全力发展2. ChatGPT于 2022年 11 月 30 日发布,它是人工智能驱动的 (2) 工具3…...
实时显示当前文件夹下的文件大小,shell脚本实现
图片来源于网络,如果侵权请联系博主删除! 需求: 写一个shell终端命令,实时显示当前文件夹下的文件大小 实现: 您可以使用以下的Shell脚本命令来实时显示当前文件夹下的文件大小: while true; docleardu …...
7、Spring之依赖注入源码解析(下)
resolveDependency()实现 该方法表示,传入一个依赖描述(DependencyDescriptor),该方法会根据该依赖描述从BeanFactory中找出对应的唯一的一个Bean对象。 @Nullable Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Null…...
图片码二次渲染绕过
目录 一、环境 1、代码 2、文件处理方式 3、图片码的制作 二、绕过图片重构 1、可行性分析 2、数据比对 3、完成绕过 一、环境 以upload-labs靶场第十七关为例 1、代码 源码为: <?php include ../config.php; include ../head.php; include ../menu.…...
点评项目核心内容
目录 拦截器设置 集群的session共享问题 基于redis实现共享session登录 创建bean对象技巧 什么是缓存 使用缓存来处理对象 使用String类型缓存来处理集合 缓存更新策略 主动更新策略 缓存穿透 空串""和null的区别 缓存null值解决穿透问题 缓存雪崩 缓存击穿…...
海外商城小程序为什么这么受欢迎?
随着全球化的进程海外商城小程序在近年来获得了广泛的关注和使用。海外商城小程序是一种基于互联网技术的应用程序,为用户提供了便捷的购物体验和跨境交易服务。本文将深入探讨海外商城小程序的受欢迎原因,从多个维度进行分析就其未来发展进行思考&#…...
Linux Day13 ---信号量
一、信号量 1.1 一些概念 用来管理对资源的访问 一个特殊的变量,只允许对它进行等待(wait)和发送信号(signal),代表可用资源个数, 取0,1 二值信号量 取 3,5 计数信号量 p操作:原子减一,代表获取资源,可能阻塞 v…...
《动手学深度学习 Pytorch版》 4.10 实战Kaggle比赛:预测比赛
4.10.1 下载和缓存数据集 import hashlib import os import tarfile import zipfile import requests#save DATA_HUB dict() DATA_URL http://d2l-data.s3-accelerate.amazonaws.com/def download(name, cache_diros.path.join(.., data)): #save"""下载一个…...
jQuery补充
文章目录 简介安装语法选择器元素选择器#id 选择器.class 选择器事件常用事件方法 效果显示隐藏淡入淡出滑动动画停止动画获取内容和属性添加元素删除元素操作css父辈 💛💛孔子云:温故而知新,可以为师矣💛💛…...
Wan2.1-umt5与Node.js后端集成:构建高并发AI服务网关
Wan2.1-umt5与Node.js后端集成:构建高并发AI服务网关 最近和几个做后端的朋友聊天,发现大家都有个共同的痛点:想把一些好用的AI模型能力集成到自己的业务系统里,但一遇到高并发场景就头疼。要么是API调用超时,要么是服…...
UEFI启动全流程拆解:从按下电源键到系统加载的幕后故事
UEFI启动全流程拆解:从按下电源键到系统加载的幕后故事 当你按下电脑的电源键,短短几秒内,一场精密的交响乐正在硬件深处悄然上演。这场演出的总指挥,正是现代计算机的启动管家——UEFI(统一可扩展固件接口࿰…...
芯片验证工程师必备:SVA断言中的assert/cover/assume核心区别与典型误用案例
芯片验证工程师必备:SVA断言中的assert/cover/assume核心区别与典型误用案例 在芯片验证领域,SystemVerilog Assertion(SVA)是验证工程师不可或缺的利器。对于1-3年经验的验证工程师而言,深入理解assert、cover和assum…...
能耗优化指南:OpenClaw+GLM-4.7-Flash笔记本续航方案
能耗优化指南:OpenClawGLM-4.7-Flash笔记本续航方案 1. 为什么需要关注OpenClaw的能耗问题 去年夏天的一次出差经历让我深刻意识到这个问题的重要性。当时我正在高铁上用笔记本调试一个OpenClaw自动化流程,结果不到两小时就收到了电量不足的警告。这促…...
Flux Sea Studio 入门:十分钟完成星图平台镜像部署并生成首张图片
Flux Sea Studio 入门:十分钟完成星图平台镜像部署并生成首张图片 想试试最近很火的AI绘画,但又觉得本地部署太麻烦,显卡要求太高?今天咱们就来聊聊一个超级省事的办法——直接在云端用Flux Sea Studio。你不需要懂代码ÿ…...
CoPaw代码生成能力展示:从自然语言描述到可运行Python脚本
CoPaw代码生成能力展示:从自然语言描述到可运行Python脚本 1. 开篇:当自然语言遇上代码生成 "能不能帮我写个Python脚本,把文件夹里的图片都转成灰度图?"这样的需求,现在可以直接说给CoPaw听。作为一款专注…...
WarcraftHelper:魔兽争霸3兼容性问题的全方位解决方案
WarcraftHelper:魔兽争霸3兼容性问题的全方位解决方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 问题发现:现代系统下的经…...
RVC效果对比实测:原声vs克隆声,你能听出区别吗?
RVC效果对比实测:原声vs克隆声,你能听出区别吗? 1. 引言:AI语音克隆技术的新突破 想象一下,你最喜欢的歌手正在用你的声音唱歌,或者你的播客节目突然有了专业播音员的音色。这不再是科幻场景,…...
PyTorch/TensorFlow张量加速实战:3个被90%工程师忽略的底层CUDA内核调优技巧
第一章:PyTorch/TensorFlow张量加速实战:3个被90%工程师忽略的底层CUDA内核调优技巧CUDA流与默认流解耦:避免隐式同步瓶颈 PyTorch 和 TensorFlow 默认将所有 CUDA 操作提交至默认流(null stream),导致跨 k…...
效果惊艳:AI超清画质增强镜像3倍放大作品集展示
效果惊艳:AI超清画质增强镜像3倍放大作品集展示 1. 低清图像的困扰与AI解决方案 你是否遇到过这样的情况:翻出多年前的老照片想重温美好回忆,却发现画面模糊不清;从网上下载的图片用作素材时,放大后却满是马赛克&…...
