STL之函数对象和谓词

1.函数对象

重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象。一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待。
这是通过重载类的operator()来实现的。
“在标准库中,函数对象被广泛地使用以获得弹性”,标准库中的很多算法都可以使用函数对象或者函数来作为自定的回调行为;

一元函数对象:函数参数1个;
二元函数对象:函数参数2个;

2.谓词

一元谓词: 函数参数1个,函数返回值是bool类型,可以作为一个判断式

二元谓词: 函数参数2个,函数返回值是bool类型

谓词可以使一个仿函数,也可以是一个回调函数。

一元谓词举例如下:
1.判断给出的string对象的长度是否小于6

bool GT6(const string &s)
{
return s.size() >= 6;
}

2.判断给出的int是否在3到8之间

bool Compare( int i )
{
return ( i >= 3 && i <= 8 );
}

二元谓词举例如下:
1.比较两个string对象,返回一个bool值,指出第一个string是否比第二个短

bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}

3.一元函数对象案例

//1普通类 重载 函数调用操作符
template <typename T>
void FuncShowElemt(T &t)  //普通函数 不能像 仿函数那样记录状态
{cout << t << " ";
};void showChar(char &t)
{cout << t << " ";
}//函数模板 重载 函数调用操作符
template <typename T>
class ShowElemt
{
public:ShowElemt(){n = 0;}void operator()(T &t){n++;cout << t << " ";}void printCount(){cout << n << endl;}
public:int n;
};//1 函数对象 基本使用
void main11()
{int a = 100;FuncShowElemt<int>(a); //普通的函数调用ShowElemt<int> showElemt; //函数对象 showElemt(a); //函数对象调用 
}

4.一元谓词案例

//1元谓词 例子
template <typename T>
class Isdiv
{
public:Isdiv(const T &divisor) //{this->divisor = divisor;}bool operator()(T &t){return (t%divisor == 0);}
protected:
private:T divisor;
};void main13()
{vector<int> v2;for (int i=10; i<33; i++){v2.push_back(i);}vector<int>::iterator it;int a = 4;Isdiv<int> mydiv(a);// _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred)   //返回的是迭代器it = find_if(v2.begin(), v2.end(), Isdiv<int>(4));if (it != v2.end()){cout << "第一个被4整除的数是:" << *it << endl;}
}

5.二元函数对象案例

template <typename T>
struct SumAdd
{T operator()(T &t1, T &t2){return t1 + t2;}
};template <typename T>
void printE(T &t)
{for (vector<int>::iterator it = t.begin(); it!=t.end(); it++ ){cout << *it << " ";}
}void printVector(vector<int> &v)
{for (vector<int>::iterator it = v.begin(); it!=v.end(); it++ ){cout << *it << " ";}
}void  main14()
{vector<int> v1, v2 ;vector<int> v3;v1.push_back(1);v1.push_back(2);v1.push_back(3);v2.push_back(4);v2.push_back(5);v2.push_back(6);v3.resize(10);//transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());/*template<class _InIt1,class _InIt2,class _OutIt,class _Fn2> inline_OutIt transform(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _OutIt _Dest, _Fn2 _Func)*/vector<int>::iterator it = transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());cout << *it << endl;printE(v3); 
}

6.二元谓词案例

void current(int &v)
{cout << v << " ";
}bool MyCompare(const int &a, const int &b)
{return a < b;
}
void main15()
{vector<int> v(10);for (int i=0; i<10; i++){v[i] = rand() % 100;}for_each(v.begin(), v.end(), current);printf("\n");sort(v.begin(), v.end(), MyCompare );printf("\n");for (int i=0; i<10; i++){printf("%d ", v[i]);}printf("\n");
}

7.综合示例代码

#include <iostream>
using namespace std;#include "string"
#include <vector>
#include <list>
#include "set"
#include <algorithm>
#include "functional"//函数对象 类重载了()
template <typename T>
class ShowElemt
{
public:ShowElemt(){n = 0;}void operator()(T &t){n ++;//printN();cout << t << " ";}void printN(){cout << "n:" << n << endl;}
protected:
private:int n;
};//函数模板  ==函数
template <typename T>
void FuncShowElemt(T &t)
{cout << t << endl;
}//普通函数
void FuncShowElemt2(int &t)
{cout << t << " ";
}//函数对象 定义 ;  函数对象和普通函数的异同 
//
void main01()
{int a = 10;ShowElemt<int> showElemt;showElemt(a); //函数对象的()的执行 很像一个函数 //仿函数FuncShowElemt<int>(a);FuncShowElemt2(a);
}//函数对象是属于类对象,能突破函数的概念,能保持调用状态信息
//函数对象的好处
// for_each算法中, 函数对象做函数参数
// for_each算法中, 函数对象当返回值
void main02()
{vector<int> v1;v1.push_back(1);v1.push_back(3);v1.push_back(5);for_each(v1.begin(), v1.end(), ShowElemt<int>()); //匿名函数对象 匿名仿函数cout << endl;for_each(v1.begin(), v1.end(), FuncShowElemt2); //通过回调函数  谁使用for_each 谁去填写回调函数的入口地址ShowElemt<int> show1;//函数对象 做函数参数 /*template<class _InIt,class _Fn1> inline_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func){   // perform function for each element_DEBUG_RANGE(_First, _Last);_DEBUG_POINTER(_Func);return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func));}*///1 for_each算法的 函数对象的传递 是元素值传递 ,不是引用传递for_each(v1.begin(), v1.end(), show1);show1.printN();cout << "通过for_each算法的返回值看调用的次数" << endl;show1 = for_each(v1.begin(), v1.end(), show1);show1.printN();//结论 要点: 分清楚 stl算法返回的值是迭代器 还是 谓词(函数对象) 是stl算法入门的重要点
}template<typename T>
class IsDiv
{
public:IsDiv(const T &divisor){this->divisor = divisor;}bool operator()(T  &t){return (t%divisor == 0);}protected:
private:T divisor;
};void main03()
{vector<int> v2;for (int i=10; i<33; i++){v2.push_back(i);}int a = 4;IsDiv<int> myDiv(a);//find_if(v2.begin(), v2.end(), myDiv );/*template<class _InIt,class _Pr> inline_InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred){   // find first satisfying _Pred_DEBUG_RANGE(_First, _Last);_DEBUG_POINTER(_Pred);return (_Rechecked(_First,_Find_if(_Unchecked(_First), _Unchecked(_Last), _Pred)));}//find_if返回值是一个迭代器 //要点: 分清楚 stl算法返回的值是迭代器 还是 谓词(函数对象) 是stl算法入门的重要点*/vector<int>::iterator it;it = find_if(v2.begin(), v2.end(), IsDiv<int>(a) );if (it == v2.end()){cout << "容器中没有被4整除的元素" << endl;}else{cout <<"第一个是被4整除的元素是:" << *it << endl;}}//二元函数对象
template <typename T>
class SumAdd
{
public:T operator()(T t1, T t2){return t1 + t2;}
};void main04()
{//v1 v2 ==> v3vector<int> v1, v2;vector<int> v3;v1.push_back(1);v1.push_back(3);v1.push_back(5);v2.push_back(2);v2.push_back(4);v2.push_back(6);v3.resize(10);/*template<class _InIt1,class _InIt2,class _OutIt,class _Fn2> inline_OutIt transform(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _OutIt _Dest, _Fn2 _Func){   // transform [_First1, _Last1) and [_First2, ...) with _Func_DEBUG_RANGE(_First1, _Last1);_DEBUG_POINTER(_Dest);_DEBUG_POINTER(_Func);if (_First1 != _Last1)return (_Transform2(_Unchecked(_First1), _Unchecked(_Last1),_First2, _Dest, _Func,_Is_checked(_Dest)));return (_Dest);}//transform 把运算结果的 迭代器的开始位置 返回出来 */transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SumAdd<int>() );for (vector<int>::iterator it=v3.begin(); it!=v3.end(); it++ ){cout << *it << " ";}cout << endl;
}bool MyCompare(const int &a, const int &b)
{return a < b; //从小到大
}void main05()
{vector<int> v1(10);for (int i=0; i<10; i++){int tmp = rand() %100;v1[i] = tmp;}for (vector<int>::iterator it=v1.begin(); it!=v1.end(); it++ ){cout << *it <<" ";}cout << endl;for_each(v1.begin(), v1.end(), FuncShowElemt2);cout << endl;sort(v1.begin(), v1.end(), MyCompare);for_each(v1.begin(), v1.end(), FuncShowElemt2);cout << endl;
}struct CompareNoCase
{bool operator()(const string &str1, const string &str2){string str1_ ;str1_.resize(str1.size() );transform(str1.begin(), str1.end(), str1_.begin(), tolower ); //预定义函数对象 string str2_ ;str2_.resize(str2.size() );transform(str2.begin(), str2.end(), str2_.begin(), tolower ); //预定义函数对象 return (str1_ < str2_); // 从小到大进行排序}
};
void  main06()
{set<string> set1;set1.insert("bbb");set1.insert("aaa");set1.insert("ccc");set<string>::iterator it = set1.find("aAa"); //find函数 默认 区分大小写if (it == set1.end()){cout << " 没有 查找到 aaa " << endl;}else{cout << " 查找到 aaa " << endl;}set<string, CompareNoCase> set2;set2.insert("bbb");set2.insert("aaa");set2.insert("ccc");set<string, CompareNoCase>::iterator it2 = set2.find("aAa");if (it2 == set2.end()){cout << " 没有 查找到 aaa " << endl;}else{cout << " 不区分大小的的查找  查找到 aaa " << endl;}}void main1111()
{//main01(); //函数对象基本概念//main02(); //函数对象的好处 函数对象做函数参数 函数对象做返回值//main03(); //一元谓词//main04(); //二元函数对象 和二元谓词//main05(); //二元函数对象 和二元谓词main06(); //二元谓词在set集合中的应用cout<<"hello..."<<endl;system("pause");return ;
}

8.预定义函数对象

标准模板库STL提前定义了很多预定义函数对象,#include <functional> 必须包含。

//1使用预定义函数对象:
//类模板plus<> 实现了: 不同类型的数据进行加法运算
void main41()
{plus<int> intAdd;int x = 10;int y = 20;int z = intAdd(x, y); //等价于 x + y cout << z << endl;plus<string> stringAdd;string myc = stringAdd("aaa", "bbb");cout << myc << endl;vector<string> v1;v1.push_back("bbb");v1.push_back("aaa");v1.push_back("ccc");v1.push_back("zzzz");//缺省情况下,sort()用底层元素类型的小于操作符以升序排列容器的元素。//为了降序,可以传递预定义的类模板greater,它调用底层元素类型的大于操作符:cout << "sort()函数排序" << endl;;sort(v1.begin(), v1.end(), greater<string>() ); //从大到小for (vector<string>::iterator it=v1.begin(); it!=v1.end(); it++ ){cout << *it << endl;}
}

8.1算术函数对象

预定义的函数对象支持加、减、乘、除、求余和取反。调用的操作符是与type相关联的实例

//加法:plus<Types>
plus<string> stringAdd;
sres = stringAdd(sva1,sva2);减法:minus<Types>
乘法:multiplies<Types>
除法divides<Tpye>
求余:modulus<Tpye>
取反:negate<Type>
negate<int> intNegate;
ires = intNegate(ires);
Ires= UnaryFunc(negate<int>(),Ival1);

8.2关系函数对象

等于equal_to<Tpye>
equal_to<string> stringEqual;
sres = stringEqual(sval1,sval2);
不等于not_equal_to<Type>
大于 greater<Type>
大于等于greater_equal<Type>
小于 less<Type>
小于等于less_equal<Type>
void main42()
{vector<string> v1;v1.push_back("bbb");v1.push_back("aaa");v1.push_back("ccc");v1.push_back("zzzz");v1.push_back("ccc");string s1 = "ccc";//int num = count_if(v1.begin(),v1.end(), equal_to<string>(),s1);int num = count_if(v1.begin(),v1.end(),bind2nd(equal_to<string>(), s1));cout << num << endl;
} 

8.3逻辑函数对象

逻辑与 logical_and<Type>
logical_and<int> indAnd;
ires = intAnd(ival1,ival2);
dres=BinaryFunc( logical_and<double>(),dval1,dval2);
逻辑或logical_or<Type>
逻辑非logical_not<Type>
logical_not<int> IntNot;
Ires = IntNot(ival1);
Dres=UnaryFunc( logical_not<double>,dval1);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448325.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装 Git ( Windows、linux、Mac)

安装 Git 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 是时候动手尝试下 Git 了&#xff0c;不过得先安装好它。有许多种安装方式&#xff0c;主要分为两种&#xff0c;一种是通过编…

会车

概念 会车&#xff0c;即反向行驶的列车、汽车等同时在某一地点交错通过。 会车攻略 一看&#xff0c;看对向来车的车型、速度和装载情况&#xff0c;前方道路的宽度、坚实情况&#xff0c;路旁行人、车辆情况&#xff0c;路旁停车以及障碍物情况等; 二算&#xff0c;…

FormsAuthenticationTicket基于forms的验证

构建基于forms的验证机制过程如下&#xff1a; 1,设置IIS为可匿名访问和asp.net web.config中设置为form验证 2,检索数据存储验证用户&#xff0c;并检索角色(如果不是基于角色可不用) 3,使用FormsAuthenticationTicket创建一个Cookie并回发到客户端&#xff0c;并存储 角色到票…

通过公共汽车站

要求 通过班车站&#xff0c;应降低速度慢行&#xff0c;挂一挡通过&#xff0c;注意左右仔细查看。操作方法 1、减速慢行&#xff0c;注意观察公共汽车周围的交通情况&#xff0c;以防突然情况的出现; 2、在超越公共汽车时&#xff0c;注意提防公共汽车起步后突然向左转…

STL之函数适配器

1.理论知识 2.常用函数适配器 标准库提供一组函数适配器&#xff0c;用来特殊化或者扩展一元和二元函数对象。常用适配器是&#xff1a; 1绑定器&#xff08;binder&#xff09;: binder通过把二元函数对象的一个实参绑定到一个特殊的值上&#xff0c;将其转换成一元函数对象…

真正理解 git fetch, git pull 以及 FETCH_HEAD

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 真正理解 git fetch, git pull 要讲清楚git fetch&#xff0c;git pull,必须要附加讲清楚git remote&#xff0c;git merge 、远程rep…

pyqt5 + pyinstaller 制作爬虫小程序

环境:mac python3.7 pyqt5 pyinstaller ps: 主要是熟悉pyqt5, 加入了单选框 输入框 文本框 文件夹选择框及日历下拉框 效果图: pyqt5 主程序文件 # -*- coding: utf-8 -*- # Author: Mehaei # Date: 2019-07-10 13:02:56 # Last Modified by: Mehaei # Last Modified time…

通过学校区域

通过学校区域的要求 应观察前后左右的交通情况&#xff0c;适时减速慢行&#xff0c;不得鸣喇叭和与学生抢行。 操作方法 当驾驶车辆行至学校附近或有注意儿童标志路段时&#xff0c;一定要及时减速&#xff0c;注意观察道路两侧或周围的情况&#xff0c;时刻堤防学生横…

axios中出现两次请求,OPTIONS请求和GET请求

在项目中发现ajax中出现两次请求&#xff0c;OPTIONS请求和GET请求 查看到浏览器NetWork有两次请求&#xff0c;请求url一样&#xff1a; 查找原因是浏览器对简单跨域请求和复杂跨域请求的处理区别。 XMLHttpRequest会遵守同源策略(same-origin policy). 也即脚本只能访问相同协…

笔试面试收获(持续更新中)

1. Internet 是有ARPANET发展而来 2. NFS&#xff08;Network File System&#xff09;即网络文件系统 3. OSI参考模型七层&#xff1a;物理层&#xff0c;数据链路层&#xff0c;网络层&#xff08;IP,路由器&#xff0c;三层交换机&#xff09;&#xff0c;传输层&#xff…

Linux 安装 配置 Maven

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.需要提前安装JDK&#xff0c;并且配置环境变量 请参考&#xff1a;https://blog.csdn.net/jiangyu1013/article/details/84321146 2.…

Threading in C#

这里推荐一些C#编程多线程的学习资料&#xff1a; http://knowledge.swanky.wu.googlepages.com/threading_in_c_sharp.html Ebook in English&#xff1a;http://cid-068f7d75d8585700.skydrive.live.com/self.aspx/ebook/threading.pdf 一些demo&#xff1a;http://cid-068f7…

经理人如何与这“六种人”打交道?

在职场中&#xff0c;我们要与不同身份、不同年龄、不同岗位、不同性别、不同性格的人打交道。在平时的实际工作接触中&#xff0c;善于与不同人打交道的经理人&#xff0c;会根据不同的情况用不同的态度和方式来对待之。 1、如何与死板的人打交道 与这样的人交往&#xff0c…

[Git高级教程 (一)] 通过 Tag 标签回退版本修复 bug

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1 前言 本系列之所以取名”Git高级教程”&#xff0c;主要是教大家解决实际工作中遇到的问题&#xff0c;要求读者会基本的Git用法和命令…

Javascript 自定义输出

缘由 前段时间再看了一些javascript的学习资料,也写的一些demo,在输出的时候一般都用alert,但这个方法会打断函数运行,用起来不是很好.还有就是console.log这个方法,这种方法原来一直以为只能在FireFox上面才能用,现在才发现主流浏览器都支持.但我的这个插件已经写的差不多了,所…

不要打2岁内和6岁后的孩子 父母必看

一位妈妈说&#xff1a;“孩子经常无理取闹&#xff0c;到超市就要买这买那&#xff0c;不给买就坐在地上哭闹。到别人家去就乱翻乱动&#xff0c;还会到人家沙发上乱蹦&#xff0c;无论你怎么说&#xff0c;孩子都不听话。每次我都会气不打一处来&#xff0c;回到家就痛打一顿…

设计模式之开放封闭原则

以下皆是个人理解如有不对请留言指出&#xff0c;谢谢&#xff01; 我就代码提出我自己个人的看法&#xff1a; 正常定义一个类例如银行工作员&#xff0c;他可以执行存款&#xff0c;付款和转账功能&#xff0c;如果在现有功能上我想添加贷款功能&#xff0c;需要在类中添加…

[Git高级教程(二)] 远程仓库版本回退方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1 简介 最近在使用git时遇到了远程分支需要版本回滚的情况&#xff0c;于是做了一下研究&#xff0c;写下这篇博客。 2 问题 如果提交了…

uplift model学习笔记

一、解决的问题&#xff1a; 通常的 Propensity Model 和 Response Model 只是给目标用户打了个分&#xff0c;并没有确保模型的结果可以使得活动的提升最大化&#xff1b;它没有告诉市场营销人员&#xff0c;哪个用户最有可能提升活动响应&#xff1b; 因此&#xff0c;需要另…

必须看透的50个错觉 人生要看透而不看破!

我们应该感谢命运的多喘&#xff0c;是它用历练使一颗脆弱心的渐渐变得坚强&#xff0c;变得对一切都充满了向往。无可否认&#xff0c;只有真正的经历了一些事物之后&#xff0c;你才会对人生看得更加透彻&#xff0c;才会对世间真情感悟的更加真切。 1、个人只能被现实改变…