C++STL函数对象的应用
STL函数对象
文章目录
- STL函数对象
- 1.基本概念
- 2.使用方法
- 1. 简单函数对象示例
- 2. 函数对象作为算法参数
- 3. Lambda表达式作为函数对象
- 2.一元谓词和二元谓词
- 1.一元谓词
- 2.二元谓词
- 3.总结
- 3.算术仿函数
- 1.使用示例
- 2.Lambda表达式的替代
- 4.关系仿函数
- 5.逻辑仿函数
C++中的函数对象(Function Object),也常被称为仿函数(Functor),是一种模拟函数行为的类对象。它们允许用户自定义操作,并能像普通函数那样被调用,同时还能携带状态,这是普通函数所不具备的能力。函数对象是实现泛型编程、算法定制等高级技术的关键组件之一。下面概述了函数对象的基本概念和使用方法:
1.基本概念
- 类定义:函数对象通常是一个重载了
()操作符的类。这个操作符使得该类的对象可以像函数一样被调用。 - 状态携带:与普通函数不同,函数对象可以拥有成员变量,从而在不同的调用之间保持状态。
- 类型要求:为了能够用于标准库算法中,函数对象需要满足可调用对象的要求,即至少要有一个
operator()成员函数。
2.使用方法
1. 简单函数对象示例
#include <iostream>// 定义一个简单的函数对象类,重载了()操作符
class Adder {
public:// 构造函数可以初始化内部状态Adder(int add_value) : value(add_value) {}// 重载()操作符,使得对象可以像函数一样被调用int operator()(int x) {return x + value;}private:int value; // 成员变量,保存加到输入值上的额外值
};int main() {Adder addFive(5); // 创建一个Adder对象,初始化加值为5std::cout << addFive(10) << std::endl; // 调用仿函数,输出15return 0;
}
2. 函数对象作为算法参数
C++标准库中的许多算法都接受函数对象作为参数,以定制其行为。例如,std::sort可以通过传递自定义比较函数来改变排序规则。
#include <algorithm>
#include <vector>
#include <iostream>// 一个用于降序比较的仿函数
struct DescComp {bool operator()(int a, int b) {return a > b;}
};int main() {std::vector<int> vec = {1, 3, 5, 2, 4};// 使用自定义的降序比较仿函数进行排序std::sort(vec.begin(), vec.end(), DescComp());for(int i : vec) {std::cout << i << " ";}// 输出:5 4 3 2 1return 0;
}
3. Lambda表达式作为函数对象
从C++11开始,Lambda表达式提供了一种更简洁的方式创建匿名函数对象,它可以直接在代码中定义并使用。
#include <algorithm>
#include <vector>
#include <iostream>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};// 使用Lambda表达式作为自定义排序规则std::sort(vec.begin(), vec.end(), [](int a, int b) {return a > b; // 降序排列});for(int i : vec) {std::cout << i << " ";}// 输出:5 4 3 2 1return 0;
}
通过上述示例,可以看到函数对象在C++中提供了强大的灵活性和定制能力,是泛型编程和算法设计中的重要工具。
2.一元谓词和二元谓词
C++中的一元谓词和二元谓词是两种特定类型的函数对象,它们在标准模板库(STL)的算法中扮演着重要的角色,用于定制算法的行为。以下是它们的基本概念和使用方法:
1.一元谓词
基本概念:
- 一元谓词是只接受一个参数的函数对象,并返回一个布尔值(
bool)。 - 这个函数对象通常用来测试或判断传入的参数是否满足某个条件。
- 在STL算法中,一元谓词常用于从容器中选择满足特定条件的元素,例如
std::find_if。
使用示例:
#include <algorithm>
#include <vector>
#include <iostream>// 一元谓词函数对象,检查一个数是否为偶数
struct IsEven {bool operator()(int x) {return x % 2 == 0;}
};int main() {std::vector<int> numbers = {1, 2, 3, 4, 5, 6};auto it = std::find_if(numbers.begin(), numbers.end(), IsEven());if(it != numbers.end())std::cout << "The first even number is: " << *it << std::endl;elsestd::cout << "No even number found." << std::endl;return 0;
}
2.二元谓词
基本概念:
- 二元谓词接受两个参数,并返回一个布尔值。
- 它们通常用于比较这两个参数是否满足某种关系,如小于、大于、等于等。
- 在STL中,二元谓词广泛应用于排序算法(如
std::sort)、查找算法(如std::binary_search)等,用以定义元素间的比较规则。
使用示例:
#include <algorithm>
#include <vector>
#include <iostream>// 二元谓词函数对象,检查第一个数是否大于第二个数
struct GreaterThan {bool operator()(int a, int b) {return a > b;}
};int main() {std::vector<int> values = {5, 2, 9, 1, 5, 6};// 使用二元谓词进行降序排序std::sort(values.begin(), values.end(), GreaterThan());for(int val : values) {std::cout << val << " ";}// 输出:9 6 5 5 2 1return 0;
}
3.总结
无论是哪种谓词,它们的核心作用都是提供一个逻辑判断,使得STL算法能够基于这些逻辑判断来处理数据。一元谓词适用于单个元素的条件筛选,而二元谓词则用于定义元素间的关系,比如排序或查找时的比较逻辑。随着C++11及之后版本对Lambda表达式的支持,直接在算法中内联定义谓词变得更加方便快捷。
3.算术仿函数
C++ STL(标准模板库)提供了一系列算术仿函数(Arithmetic Functors),它们是对基本数学运算的封装,使得这些运算可以像函数对象一样被使用,尤其是在算法中进行定制操作时非常有用。以下是一些常用的算术仿函数及其简单说明:
- plus:定义了加法操作,重载了
operator()以执行加法。 - minus:定义了减法操作。
- multiplies:实现了乘法操作。
- divides:提供了除法操作。
- modulus:用于取模运算。
- negate:执行取负操作。
1.使用示例
这些仿函数位于<functional>头文件。
#include <iostream>
#include <functional>
#include <algorithm> // 用于std::transformint main() {std::vector<int> numbers = {1, 2, 3, 4, 5};std::vector<int> results;// 使用plus仿函数将每个元素自身相加(即每个元素乘以2)results.resize(numbers.size());std::transform(numbers.begin(), numbers.end(), results.begin(), std::plus<int>());// 输出结果for(int res : results) {std::cout << res << " ";}// 输出:2 4 6 8 10return 0;
}
在这个例子中,std::transform算法结合std::plus<int>()仿函数,将numbers容器中的每个元素与其自身相加,结果存储在results容器中。
2.Lambda表达式的替代
虽然算术仿函数非常有用,但在C++11及以后的版本中,Lambda表达式提供了更加灵活和直观的方式来定义这样的操作,特别是在复杂逻辑或需要访问外部变量时。然而,对于简单的数学运算,直接使用STL提供的算术仿函数可以简化代码,提高可读性。
4.关系仿函数
关系仿函数封装了基本的比较运算符,位于<functional>头文件中。
- equal_to:测试两个参数是否相等。
- not_equal_to:测试两个参数是否不相等。
- greater:测试第一个参数是否大于第二个参数。
- less:测试第一个参数是否小于第二个参数。
- greater_equal:测试第一个参数是否大于等于第二个参数。
- less_equal:测试第一个参数是否小于等于第二个参数。
#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};int target = 3;// 使用equal_to查找目标值if(std::find_if(vec.begin(), vec.end(), std::bind2nd(std::equal_to<int>(), target)) != vec.end()) {std::cout << target << " is found in the vector." << std::endl;} else {std::cout << target << " is not found in the vector." << std::endl;}return 0;}
5.逻辑仿函数
逻辑仿函数用于组合或反转布尔值,它们也是在<functional>中定义的,包括:
- logical_and:对两个布尔值执行逻辑与操作。
- logical_or:对两个布尔值执行逻辑或操作。
- logical_not:对一个布尔值执行逻辑非操作。
逻辑仿函数示例
#include <iostream>
#include <functional>int main() {bool flag1 = true, flag2 = false;// 使用逻辑与if(std::logical_and<bool>()(flag1, flag2)) {std::cout << "Both flags are true." << std::endl;} else {std::cout << "Not both flags are true." << std::endl;}// 使用逻辑或if(std::logical_or<bool>()(flag1, flag2)) {std::cout << "At least one flag is true." << std::endl;}// 使用逻辑非std::cout << "Negation of flag2: " << std::logical_not<bool>()(flag2) << std::endl;return 0;
}
相关文章:
C++STL函数对象的应用
STL函数对象 文章目录 STL函数对象1.基本概念2.使用方法1. 简单函数对象示例2. 函数对象作为算法参数3. Lambda表达式作为函数对象 2.一元谓词和二元谓词1.一元谓词2.二元谓词3.总结 3.算术仿函数1.使用示例2.Lambda表达式的替代 4.关系仿函数5.逻辑仿函数 C中的函数对象&#…...
AJAX-day1:
注:文件布局: 一、AJAX的概念: AJAX是浏览器与服务器进行数据通信的技术 >把数据变活 二、AJAX的使用: 使用axios库,与服务器进行数据通信 基于XMLHttpRequest封装,代码简单 Vue,React项目使用 学习…...
昆虫学(书籍学习资料)
包括昆虫分类(上下册)、昆虫生态大图鉴等书籍资料。...
springboot + mybatis 多数据源切换
参考的b站博主写的 配置文件: spring:datasource:db1:jdbc-url: jdbc:mysql://localhost:3306/interview_database?useUnicodetrue&characterEncodingutf-8&useSSLfalseusername: rootpassword: 12345driver-class-name: com.mysql.cj.jdbc.Driverdb2:jdbc-url: jdbc…...
windows电脑网络重置后wifi列表消失怎么办?
我们的电脑网络偶尔会出现异常,我们通常会下意识选择网络诊断,运行完诊断后一般会让我们选择重置网络,然而,重置后wifi列表突然消失,无法愉快地上网了,找了一圈,都说是更改适配器选项࿰…...
Python + 在线 + 文生音,音转文(中文文本转为英文语音,语音转为中文文本)
开源模型 平台:https://huggingface.co/ars-语言转文本: pipeline("automatic-speech-recognition", model"openai/whisper-large-v3", device0 ) hf: https://huggingface.co/openai/whisper-large-v3 github: https://github.com/openai/wh…...
哏号分治,CF103D - Time to Raid Cowavans
一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 103D - Time to Raid Cowavans 二、解题报告 1、思路分析 想了半天数据结构最终选择根号分治 我们考虑 大于 550 的公差直接暴力 小于550 的公差的所有询问,我们直接计算该公差后缀和…...
基于深度学习的图像背景剔除
在过去几年的机器学习领域,我一直想打造真正的机器学习产品。 几个月前,在参加了精彩的 Fast.AI 深度学习课程后,似乎一切皆有可能,我有机会:深度学习技术的进步使许多以前不可能实现的事情成为可能,而且开…...
Python使用(...)连接字符串
Python 字符串连接的灵活性。 使用括号来组织多行字符串时的自动拼接。 e e var_str g*3connect_str (fa{e}bcvar_strh )print(connect_str) print(type(connect_str)) 运行结果: aebcgggh <class str> 解释: 定义变量: e e:…...
鸿蒙:1.入门
概述 简介 鸿蒙操作系统(HarmonyOS)是华为公司发布的一款智能终端系统,是基于微内核的面向全场景的分布式操作系统。它致力于提供更加安全、高效、低延迟、低功耗的操作体验,可通过技术手段对应用程序和设备进行智能协同…...
【matlab】智能优化算法——求解目标函数
智能优化算法在求解目标函数方面发挥着重要作用,它通过迭代、筛选等方法来寻找目标函数的最优值(极值)。以下是关于智能优化算法求解目标函数的详细介绍: 一、智能优化算法概述 智能优化算法是一种搜索算法,旨在通过…...
不改代码,实现web.config或app.config的连接字符串加密解密
目的:加密字符串,防止明文显示。 好处:不用修改代码,微软自带功能,自动解密。 web.config 参考相关文章: Walkthrough: Encrypting Configuration Information Using Protected Configuration | Microso…...
Python创建MySQL数据库
一、使用Docker部署本地MySQL数据库 docker run --restartalways -p 3307:3306 --name mysql -e MYSOL_ROOT_PASSWORDlms123456 -d mysql:8.0.25 参数解析: 用户名:root 密码:lms123456 端口:3307 二、在Pycharm开发工具中配置连接MySQL数据库 三、安装zdppy_mysql pip inst…...
【C++】unordered系列容器的封装
你很自由 充满了无限可能 这是很棒的事 我衷心祈祷你可以相信自己 无悔地燃烧自己的人生 -- 东野圭吾 《解忧杂货店》 unordered系列的封装 1 unordered_map 和 unordered_set2 改造哈希桶2.1 模版参数2.2 加入迭代器 3 上层封装3.1 unordered_set3.2 unordered_map 4 面…...
matlab 超越椭圆函数图像绘制
matlab 超越椭圆函数图像绘制 超越椭圆函数图像绘制xy交叉项引入斜线负向斜线成分正向斜线成分 x^2 y^2 xy 1 (负向)绘制结果 x^2 y^2 - xy 1 (正向)绘制结果 超越椭圆函数图像绘制 xy交叉项引入斜线 相对于标准圆…...
本地文件同步上传到Gitee远程仓库
1、打开我们的项目所在文件夹 2、在项目文件夹【鼠标右击】弹出菜单,在【鼠标右击】弹出的菜单中,点击【Git Bash Here】,弹出运行窗口(前提条件是已装好git环境) 3、在命令窗口中输入:git init 4、在 Gite…...
RESTful Web 服务详解
RESTful Web 服务是一种基于 Representational State Transfer (REST) 架构风格的 Web 服务,它利用 HTTP 协议来传输数据,支持多种数据格式如 JSON 和 XML。在 Spring 框架中,通过简单配置和注解可以轻松实现 RESTful Web 服务。在本文中&…...
【ARMv8/v9 GIC 系列 5.3 -- 系统寄存器对中断的处理】
请阅读【ARM GICv3/v4 实战学习 】 文章目录 ARMv8/v9系统寄存器对中断的控制Group 0中断的寄存器Group 1中断的寄存器安全状态与中断分组中断处理过程中断确认处理代码中断完成处理代码ARMv8/v9系统寄存器对中断的控制 在ARM GIC 体系结构中,中断分组通过一系列系统寄存器进…...
MUNIK解读ISO26262--系统架构
功能安全之系统阶段-系统架构 我们来浅析下功能安全系统阶段重要话题——“系统架构” 目录概览: 系统架构的作用系统架构类型系统架构层级的相关安全机制梳理 1.系统架构的作用 架构的思维包括抽象思维、分层思维、结构化思维和演化思维。通过将复杂系统分解…...
STM32第十五课:LCD屏幕及应用
文章目录 需求一、LCD显示屏二、全屏图片三、数据显示1.显示欢迎词2.显示温湿度3.显示当前时间 四、需求实现代码 需求 1.在LCD屏上显示一张全屏图片。 2.在LCD屏上显示当前时间,温度,湿度。 一、LCD显示屏 液晶显示器,简称 LCD(Liquid Cry…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
