当前位置: 首页 > news >正文

C++仿函数以及STL内置仿函数

仿函数又称函数对象,本质是重载了operator()运算符的类的对象,可以和普通函数一样被调用。

一、仿函数基础概念

1. 什么是仿函数

仿函数不是函数,而是一个类类型的对象。当我们给这个对象加上()调用运算符时,它会触发类中重载的operator(),从而实现类似函数的行为。

最简单的仿函数示例

#include <iostream> using namespace std; // 定义仿函数类 struct Add { // 重载函数调用运算符 int operator()(int a, int b) const { return a + b; } }; int main() { Add add; // 创建仿函数对象 cout << add(3, 5) << endl; // 像函数一样调用,输出8 cout << Add()(10, 20) << endl; // 临时对象调用,输出30 return 0; }

2. 仿函数的核心优势(为什么不用普通函数?)

仿函数解决了普通函数和函数指针的诸多局限性,是 STL 首选的可调用对象形式:

特性普通函数函数指针仿函数
携带状态❌ 只能通过全局变量❌ 只能通过全局变量✅ 可以作为类成员变量存储状态
性能可内联❌ 间接调用,无法内联✅ 编译器可直接内联operator()
类型安全❌ 类型擦除,易出错✅ 每个仿函数都是独立类型
泛型支持✅ 完美适配模板元编程
可组合性✅ 可通过适配器灵活组合

3. 仿函数的分类

根据operator()接受的参数个数,仿函数分为:

  • 一元仿函数:接受 1 个参数,如negate<int>
  • 二元仿函数:接受 2 个参数,如plus<int>
  • 多元仿函数:C++11 后支持,但 STL 内置仿函数最多二元

二、STL 内置仿函数全解

STL 在<functional>头文件中提供了一套完整的通用仿函数,覆盖了所有基础运算,无需我们重复编写。它们都是模板类,可以适配任意数值类型。

1. 算术运算仿函数

用于执行基本的算术计算,全部是二元仿函数(除了negate是一元)。

仿函数功能等价表达式
plus<T>加法a + b
minus<T>减法a - b
multiplies<T>乘法a * b
divides<T>除法a / b
modulus<T>取模a % b
negate<T>取反(一元)-a

使用示例

#include <vector> #include <algorithm> #include <functional> using namespace std; int main() { vector<int> a = {1, 2, 3, 4}; vector<int> b = {10, 20, 30, 40}; vector<int> c(4); // 两个数组对应元素相加 transform(a.begin(), a.end(), b.begin(), c.begin(), plus<int>()); // c = {11, 22, 33, 44} // 所有元素取反 transform(a.begin(), a.end(), a.begin(), negate<int>()); // a = {-1, -2, -3, -4} return 0; }

2. 关系运算仿函数

用于比较两个值的大小关系,全部是二元仿函数,返回bool类型。

仿函数功能等价表达式
equal_to<T>等于a == b
not_equal_to<T>不等于a != b
less<T>小于a < b
greater<T>大于a > b
less_equal<T>小于等于a <= b
greater_equal<T>大于等于a >= b

高频使用场景

#include <vector> #include <algorithm> #include <functional> using namespace std; int main() { vector<int> v = {3, 1, 4, 1, 5, 9}; // 降序排序(默认是less<int>()升序) sort(v.begin(), v.end(), greater<int>()); // v = {9, 5, 4, 3, 1, 1} // 统计大于5的元素个数 int cnt = count_if(v.begin(), v.end(), bind(greater<int>(), placeholders::_1, 5)); // cnt = 1 return 0; }

⚠️面试重点std::sort默认使用less<T>(),实现升序排列;std::map/std::set默认也使用less<T>作为比较器,保证元素按升序存储。

3. 逻辑运算仿函数

用于执行布尔逻辑运算,返回bool类型。

仿函数功能等价表达式
logical_and<T>逻辑与a && b
logical_or<T>逻辑或`ab`
logical_not<T>逻辑非(一元)!a

使用示例

#include <vector> #include <algorithm> #include <functional> using namespace std; int main() { vector<int> v = {1, 6, 12, 18, 25}; // 查找大于5且小于20的第一个元素 auto it = find_if(v.begin(), v.end(), [](int x) { return logical_and<int>()(greater<int>()(x, 5), less<int>()(x, 20)); }); // it指向6 return 0; }

4. 位运算仿函数(C++11 新增)

用于执行整数的位运算。

仿函数功能等价表达式
bit_and<T>按位与a & b
bit_or<T>按位或`ab`
bit_xor<T>按位异或a ^ b
bit_not<T>按位取反(C++14)~a
http://www.zskr.cn/news/1458035.html

相关文章:

  • 不止于抓包:用mitmdump+Python脚本实现App请求自动修改与数据清洗
  • Python为何成为TVA的神经与感官系统(5)
  • 终极指南:用OpenCore Legacy Patcher让旧Mac运行最新macOS的完整教程
  • GPT-5.5+具身智能:保险理赔流程重铸的临界点
  • 秩基半参数拟似然协方差估计方法解析与应用
  • 终极指南:5步让老旧Mac重获新生,运行最新macOS系统
  • 别再手动写C接口了!用Simulink Coder把模型一键打包成DLL(附VS2015配置避坑)
  • Python为何成为TVA的神经与感官系统(7)
  • 从割裂到共生:AI工具与CMS/CDP/DRM系统深度整合的12个关键接口协议详解
  • 使用LLaMA Factory微调Qwen2-0.5B:从零开始定制你的AI助手
  • AI内容生成×精准投放×实时归因——智能营销黄金三角落地手册(含GDPR合规配置模板)
  • Anki记忆卡片工具完整指南:如何用科学方法高效记忆知识
  • 测试左移遇上AI右延:当ChatGPT生成用例、Claude分析日志、LLM驱动探索性测试——你还在手动点点点?
  • 2026年专业的天津和平企业搬家/天津南开大件搬家公司高分推荐 - 品牌宣传支持者
  • CANN社区SoftmaxCrossEntropyWithLogits算子设计
  • 实战指南:基于快马平台开发符合国内需求的ai儿童故事生成器
  • 如何快速掌握OpenCode:面向开发者的开源AI编程助手完整指南
  • 计算机毕业设计之基于hadoop的社交媒体情感分析系统设计与实现
  • 数据标注避坑指南:解决Labelme闪退,从图片格式到文件路径的完整自查清单
  • 手把手教你用STM32CubeMX配置TM1616数码管驱动(附完整代码和原理图)
  • MATLAB一键运行的心电基线漂移校正工具(小波法,含对比图与多小波支持)
  • 解决90%的关键词提取难题:bert-uncased-keyword-extractor常见问题与解决方案
  • 2026年质量好的一体化混凝土浇筑地坪/环氧砂浆地坪/PVC防静电地坪/环氧防静电地坪厂家综合对比分析 - 品牌宣传支持者
  • DeepSeek V4 vs Claude Code实测:PDF结构化提取的工程化选型指南
  • 企业级AI-VR协同平台搭建:从NVIDIA Omniverse Connect配置到自研空间意图识别模型(含GitHub私有仓库邀请码)
  • BigVGAN-v2_22khz_80band_256x实战教程:用PyTorch实现从梅尔谱图到高质量音频的转换
  • Monodepth2无监督单目深度估计与三维重建实战包(含KITTI预处理、训练推理代码、答辩材料)
  • MongoDB Compass新手避坑指南:从连接数据库到安全删除数据的完整流程
  • BitCPM4-CANN与MiniCPM4对比:95.7%精度保留的量化奇迹
  • AI工作流中枢:构建可落地的自主编码与跨软件办公系统