C++ STL 函数对象的基本使用 一元谓词和二元谓词 find_if和sort源码解析
创始人
2025-05-28 15:20:03
0

STL- 函数对象

文章目录

  • STL- 函数对象
    • 1 函数对象
      • 1.1 函数对象概念
      • 1.2 函数对象使用
    • 2. 谓词
      • 2.1 谓词概念
      • 2.2 一元谓词
      • 2.3 二元谓词

1 函数对象

1.1 函数对象概念

概念:

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

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

1.2 函数对象使用

特点:

  • 函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值
  • 函数对象超出普通函数的概念,函数对象可以有自己的状态。因为函数对象本质是一个类,类中的成员属性可以记录状态
  • 函数对象可以作为参数传递

代码示例:

//1、函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值
class MyAdd
{
public:int operator()(int v1, int v2)//有参数,有返回值{return v1 + v2;}
};void test1()
{MyAdd myadd;//创建函数对象cout << "函数对象特点1:类似普通函数的调用,有参数、有返回值" << endl;cout << "myadd = " << myadd(10, 20) << endl;cout << string(50, '-') << endl;
}//2、函数对象超出普通函数的概念,函数对象可以有自己的状态
class MyPrint
{
public:MyPrint(){this->count = 0;//初始化为0}void operator()(string test){cout << test << endl;this->count++;//调用一次就记录一次}int count;//内部自己状态
};void test2()
{MyPrint myprint;//创建函数对象cout << "函数对象特点2:函数对象可以有自己的状态" << endl;myprint("Keep working out!");//函数对象调用myprint("Keep fitting!");myprint("Keep slenderizing!");cout << "myprint调用次数为:" << myprint.count << endl;cout << string(50, '-') << endl;
}//3、函数对象可以作为参数传递
void doPrint(MyPrint& myprint, string test)
{myprint(test);
}void test3()
{MyPrint myprint;//创建函数对象cout << "函数对象特点3:函数对象作为参数传递" << endl;doPrint(myprint, "Bella要减肥");//函数对象作为参数传递cout << string(50, '-') << endl;
}

在这里插入图片描述

函数对象的特点1,其实在之前的学习笔记中有使用过,比如在list容器、set容器和map容器这几个容器的自定义数据类型排序以及内置数据类型的降序排序都使用过。
对于特点2,普通函数没有函数对象这样可以有成员属性来记录本身的状态,比如统计函数的调用次数,因为函数对象本质是一个类,类是可以有成员属性的。
对于特点3,函数对象可以做为一个参数传递。

总结: 仿函数写法非常灵活,可以作为参数进行传递。

2. 谓词

2.1 谓词概念

概念:

  • 返回bool类型仿函数称为谓词
  • 如果operator()接受一个参数,即形参列表中有一个参数,叫一元谓词
  • 如果operator()接受两个参数,即形参列表中有两个参数,叫二元谓词

2.2 一元谓词

代码示例:

class LargerthanSix
{
public:bool operator()(int val)//布尔类型的仿函数{return val > 6;}
};void test1()
{vector v;for (int i = 0; i < 10; i++){v.push_back(1 + i);}//在容器中找是否有大于6的元素可以用find_if//LargerthanSix() 创建匿名的函数对象(仿函数)vector::iterator it = find_if(v.begin(), v.end(), LargerthanSix());//输出全部大于6的结果for (; it != v.end(); it++){cout << "比6大的数有:" << *it << endl;if (it == v.end()){cout << "没有比6大的数!" << endl;break;}}
}

在这里插入图片描述

注意点:
首先,find_if函数的第一个和第二个参数是迭代器,表示一个区间中查找;第三个参数是仿函数,如果看到pred表示需要传入一个仿函数,下图示
在这里插入图片描述
其次,选中find_if→右键→转到定义 查看源码,find_if的返回值是一个迭代器
在这里插入图片描述
以上是find_if源码,说明如下

  1. find_if的参数列表:_First和 _Last都是迭代器,表示查找的区间,_Pred是仿函数,其中 _Last还使用了const来修饰。
  2. find_if的返回值:最后return的部分,返回的还是_First,说明最后返回的是一个迭代器。旁边的注释还说明了,find_if返回第一个满足仿函数条件的迭代器。
  3. find_if的for循环就是find_if的实现部分:_UFirst逐步遍历容器,循环结束的条件就是起始迭代器不等于结束迭代器。
  4. 通过if语句来实现满足条件值的查找:_Pred利用重载的()调用代码写的仿函数,通过星号* 解引用使得迭代器访问容器的数据,然后传给仿函数判断当前数据是否满足条件。具体来说,*_UFirst这个数据传给仿函数_Pred,如果返回真,说明找到满足条件的值,break结束循环,最后返回。如果返回假,_UFirst移动,直到_UFirst等于结束迭代器_ULast。

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

2.3 二元谓词

示例:

class Mysort
{
public:bool operator()(int v1, int v2)//布尔类型的仿函数{return v1 > v2;}
};void test1()
{vector v;v.push_back(30);v.push_back(18);v.push_back(28);v.push_back(23);v.push_back(25);v.push_back(26);cout << "标准算法sort排序 升序\nv:  ";sort(v.begin(), v.end());for(vector::iterator it=v.begin();it!=v.end();it++){cout << *it << "  ";}cout << endl << string(40, '-') << endl;//使用函数对象 改变算法排序规则 降序cout << "\n制定算法sort排序 降序\nv:  ";sort(v.begin(), v.end(), Mysort());//Mysort() 匿名对象for (vector::iterator it = v.begin(); it != v.end(); it++){cout << *it << "  ";}cout << endl << string(40, '-') << endl;
}

在这里插入图片描述
这个sort算法当中需要的是一个谓词,因此仿函数是bool类型。
在这里插入图片描述

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

相关内容

热门资讯

贵州茅台披露市场化运营方案,公... 1月13日晚,贵州茅台发布第四届董事会2026年度第一次会议决议公告,审议通过《2026年贵州茅台酒...
业绩承压之际,海底捞打出“创始... 近日,海底捞(06862.HK)创始人张勇回归CEO位置,带着一批年轻高管进入董事会,这一“老将坐镇...
流量太大了,一夜涨粉200万的... 2026年第一波泼天流量来了,这次砸中了一个网民叫呆呆的重庆姑娘。短短2天时间,她的抖音账号粉丝已经...
美联储的天塌了?特朗普当面问罪... 特朗普当面问罪,美联储的天塌了!因为美联储办公楼的翻修工程支出超标,堂堂的美联储主席,在全球金融市场...
德邦股份拟主动退市 2026.01.13德邦股份公告,公司拟以股东会决议方式主动撤回A股股票在上海证券交易所的上市交易,...
官方通报“4名评标专家在评标过... 近日,青海省数据局发布情况通报称,1月4日,在开展跨省远程项目评标过程中,随机抽取的4名评标专家因送...
755亿渝农商行,75后刘小军... 【高管动态】2025年4月,75后刘小军被提名为渝农商行执行董事候选人,5月当选为执行董事出任董事长...
分红、减持并举 毛戈平家族两年... 中经记者 刘旺 北京报道近日,毛戈平(01318.HK)“家族式”减持引发了广泛关注。该公司公告称,...
兆易创新正式登陆港股 市值16... 中经记者 陈佳岚 广州报道1月13日,存储芯片厂商兆易创新(03986.HK)在港交所主板挂牌上市。...
美股中概股普遍回调 1月13日,美股三大指数 开盘 小幅波动,截至发稿,道指跌0.08%,标普500指数涨0.04%。 ...