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

C++高阶笔记第四篇:STL-函数对象

一、函数对象

1.函数对象概念

概念:

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

本质:

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

2.函数对象使用

特点:

  • 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
  • 函数对象超出普通函数的概念,函数对象可以有自己的状态(成员属性等...)
  • 函数对象可以作为参数传递 

示例:

//1.函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
//运算两个数的仿函数
class MyAdd
{
public:int operator()(int a, int b){return a + b;}
};
void test01()
{MyAdd Add;cout <<"10 + 20 = " << Add(10, 20) << endl;
}//2.函数对象超出普通函数的概念,函数对象可以有自己的状态(成员属性等...)//负责打印字符串的仿函数
class Myprint
{
public:Myprint(){this->count = 0;}void operator()(string print){cout << print << endl;this->count++;//每调用一次仿函数就++一次}int count;//可以有自己的状态
};
void test02()
{Myprint mp;mp("hello world");mp("hello world");mp("hello world");mp("hello world");mp("hello world");cout << "调用仿函数mp的次数:>" << mp.count << endl;
}//3.函数对象可以作为参数传递 
void Doprint(Myprint& mp, string print)
{mp(print);
}
void test03()
{Myprint mp;Doprint(mp, "hello C++");//仿函数(函数对象)可以作为参数传递
}
int main()
{test01();test02();test03();return 0;
}

运行代码:

二、谓词

1.谓词概念

概念:

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

比如:上一篇STL容器笔记set和map排序规则需要的就是谓词,需要两个参数比较返回bool判断所以是二元谓词

2.一元谓词

记住,只要见到函数需要_Pr _Pred就说明这个是谓词

示例:

//创建一元谓词
class GreaterFive
{
public://返回类型为bool,并且参数只有一个,就是一元谓词bool operator()(int val){return val > 5;//判断参数val是否大于5}
};
int main()
{vector<int> v;int i = 0;for (i = 0; i < 10; i++){v.push_back(i + 1);}//创建一个匿名的函数对象(仿函数)调用find_if//find_if是查找容器中是否有大于5的数,有就返回迭代器,没有就返回end()vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());if (it == v.end()){cout << "没有大于5的数" << endl;}else{cout << *it << endl;}return 0;
}

代码运行:

总结:参数只有一个的谓词,称为一元谓词

3.二元谓词

示例:

class Compare
{
public://二元谓词bool operator()(int val1, int val2){return val1 > val2;}
};
int main()
{vector<int>v;int i = 0;for (i = 0; i < 5; i++){v.push_back(i + 1);}sort(v.begin(), v.end(), Compare());for (vector<int>::iterator it = v.begin(); it < v.end(); it++){cout << *it << " ";}cout << endl;return 0;
}

运行代码:

总结:参数有两个的谓词,称为二元谓词

三、内建函数对象

1.内建函数对象意义

概念:

  • STL内建了一些函数对象

分类:

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

用法:

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

2.算术仿函数

功能描述:

  • 实现四则运算
  • 其中negate是一元运算,其他都是二元运算

仿函数原型:

template<class T> T plus <T>  //加法仿函数template<class T> T minus <T>  //减法仿函数template<class T> T multiplies <T>  //乘法仿函数template<class T> T divides <T>  //除法仿函数template<class T> T modulus <T>  //取模仿函数template<class T> T negate <T>  //取反仿函数

这里的算术仿函数太多了,我就挑一个一元和一个二元放入示例:

int main()
{//一元运算int x = 50;negate<int>neg;cout << neg(x) << endl;//-50//二元运算int a = 10;int b = 20;plus<int>add;cout << add(10, 20) << endl;//30return 0;
}

运算代码:

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

3.关系仿函数

功能描述:

  • 实现关系对比

仿函数原型:

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>  //小于等于

这些都是谓词,是内建的谓词,实际上我们最常用的还是greater(大于)

原因:只要是排序算法函数或成员函数,默认的仿函数都是小于,也就是升序,我们只有在降序的时候才会使用大于仿函数,其他的基本不用

示例:

int main()
{vector<int>v;int i = 0;for (i = 0; i < 5; i++){v.push_back(i + 1);}//传一个匿名的内建函数对象大于sort(v.begin(), v.end(), greater<int>());for (vector<int>::iterator it = v.begin(); it < v.end(); it++){cout << *it << " ";}cout << endl;return 0;
}

运行代码:

总结:关系仿函数中最常用的就是greater<>大于

4.逻辑仿函数

功能描述:

  • 实现逻辑运算

函数原型:

template<class T> bool logical_and <T>  //逻辑与template<class T> bool logical_or <T>  //逻辑或template<class T> bool logical_not <T>  //逻辑异或

示例: 

void printVector(vector<bool>&v)
{for (vector<bool>::iterator it = v.begin(); it < v.end(); it++){cout << *it << " ";}cout << endl;
}
int main()
{vector<bool>v1;v1.push_back(true);v1.push_back(false);v1.push_back(false);v1.push_back(true);v1.push_back(true);printVector(v1);//创建一个容器v2,将容器v1中的所有数据异或后存入v2vector<bool>v2;v2.resize(v1.size());//给v2的空间开辟为v1元素个大小空间//接下来是一个算法库的算法,后面笔记会学到//这个算法是指定一个区间,将这个区间拷贝到指定位置//并将这个区间的每个元素经过自己传入的逻辑取反的仿函数逻辑取反后插入v2容器transform(v1.begin(), v1.end(), v2.begin(), logical_not<bool>());printVector(v2);return 0;
}

代码运行:

总结:逻辑仿函数实际应用较少,了解即可

transform是算法库中的一种算法,是遍历算法,刚才使用时我们知道这个算法是将一个容器区间的元素插入一个指定位置,这个算法在下一篇的STL算法笔记中会介绍

STL函数对象笔记已学完

http://www.dtcms.com/a/313500.html

相关文章:

  • 【Leetcode】2106. 摘水果
  • Yakit热加载魔术方法模版插件语法JSRpc进阶调用接口联动
  • 【Bluedroid】btif_av_handle_event 流程源码解析
  • 更换KR100门禁读头&主机
  • UART串口常用库函数(STC8系列)
  • LLM大模型开发-SpringAI:ChatClient、Ollama、Advisor
  • greenfoot主要api
  • 广东省省考备考(第六十五天8.3)——判断推理:图形推理(数量规律题目总结)
  • 使用C++实现日志(3)
  • sqli-labs:Less-23关卡详细解析
  • C的数据类型与变量
  • 2025 Java开发真实试题-阿里面试题分析
  • C语言与数据结构:从基础到实战
  • 机器学习——过采样(OverSampling),解决类别不平衡问题,案例:逻辑回归 信用卡欺诈检测
  • 前端工程化:Vue3(一)
  • 2025年EAAI SCI1区TOP,森林救援调度与路径规划:一种新型蚁群优化算法应用,深度解析+性能实测
  • 智能化门禁常见问题处理思路
  • Linux mount挂载选项详解(重点关注nosuid)
  • 使用Perl和库WWW::Curl的爬虫程序!
  • [spring-cloud: 服务注册]-源码解析
  • Spring Boot AOP 优雅实现异常重试机制
  • 多线程异步日志系统与实现及 TCP/IP C/S 模型
  • IO流-字节流-FileOutputStream
  • day50预训练模型 CBAM注意力
  • Effective C++ 条款20:宁以pass-by-reference-to-const替换pass-by-value
  • LeetCode 2122.还原原数组
  • centos7安装桌面客户软件并远程连接
  • 学习笔记《区块链技术与应用》第五天 分叉
  • Matlab 高斯牛顿法拟合曲线
  • 力扣-200.岛屿数量