C++中的仿函数functor
引子
先考虑一个简单的例子:假设有一个vector<string>
,你的任务是统计长度小于5的string
的个数,如果使用count_if
函数的话,你的代码:
bool LessThan5Function(const string& str) {//寻找长度小于5的字符串return str.length() < 5;
}void test() {vector<string> sVec{ "sadaw","srfafas","12" };int count = count_if(sVec.begin(), sVec.end(), LessThan5Function);//寻找容器中长度小于5的字符串的数量
}
在这里count_if
函数的第三个参数是一个函数指针,返回一个bool
类型的值。一般的,如果需要指定这个长度len
作为参数传入的话,我们可能将函数写成这样:
bool LessThan5Function(const string& str,size_t len) {//寻找长度小于5的字符串return str.length() < len;
}
这个函数看起来比前面一个版本看起来OK,因为更加具有可操作性,但是他不能满足这个泛型函数count_if
的参数要求:count_if
要求的函数是unary function
(仅带有一个参数的函数)。
我们如何才能在只能传入一个参数的情况下使用这个count_if
,并且指定自己想要的参数,而且,不需要改变这个函数本身,比如如果我们要小于7的字符串数量,就得将传入的函数写成这样的话,正常人都会崩溃的
bool LessThan7Function(const string& str) {return str.length() < 7;
}
一般这种情况怎么办?
我们应该会想到用一个全局变量
int maxLength = 5;
bool LessThan5Function(const string& str) {//寻找长度小于5的字符串return str.length() < maxLength;
}
但是全局变量的缺点相信大家都很清楚:
- 污染命名空间(多人协同,冲突)
- 每次修改功能还是需要去修改这个全局变量
- 不具有重复使用的功能(比如多个要用到这个函数指针的泛函数)
所以,说了这么多,我们需要的是一个什么东西呢?
我们需要一个能够实现函数功能,并且可以携带我们需要的数据(比如上面的字符串长度),最后最重要的:不会因为多个人同时使用,而造成功能冲突和混乱,的这样的一个东西
这就是我将要介绍的仿函数:
仿函数
借用一下百度百科的解释:
仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是在类中实现一个
operator()
,这个类就有了类似函数的行为,就是一个仿函数类了。
将上面的那个函数,用仿函数的方式改写了之后是什么样子?
class LessThan5Functor {
public:bool operator ()(const string& str) {//寻找长度小于5的字符串return str.length() < 5;}
};
就是一个简单的operator ()
操作符的重写,但是仿函数和上面的函数指针不同的一点就是:它是一个对象
什么意思呢?
就是这是一个可以被实例化的、具有内存的、可存储数据的实体
想一下,上面的函数指针,我们想要携带数据进入那个count_if
是多么的麻烦和不具有普适性,而仿函数的出现,就是为了兼容STL
的标准
仿函数的使用
int main()
{greater<int > gt;cout << gt(1, 2) << endl;//false; (1)cout << greater<int >()(6, 4) << endl;//true; (2)system("pause");return 0;
}
上面的代码,就是一个仿函数的使用例子,我们定义了一个greater<int>
的对象gt
,(1) 中gt(1, 2)
就是直接调用了greater<int> gt
的的operator ()
函数
而(2)是定义了一个greater<int>
的局部变量,然后调用其operator ()
函数,在(2)的这行代码结束后,这个greater<int>
的局部变量就被回收了(临时对象)
善用仿函数的成员变量
针对最开始我们说的多个参数问题,我们可以如何解决呢?
int count = count_if(sVec.begin(), sVec.end(), LessThan5Functor);//寻找容器中长度小于5的字符串的数量
我们可以传入一个LessThanLenFunctor
的仿函数对象作为参数,这个对象内部保存了长度信息,LessThanLenFunctor
的对象实现如下:
class LessThanLenFunctor {
public:bool operator ()(const string& str) {//寻找长度小于5的字符串return str.length() < len;}LessThanLenFunctor(int l):len(l) {}
private:int len ;
};
这样我们就避免了使用全局变量的那几个问题,而且,非常优雅且有用,我们如何去使用这个仿函数呢?
如下,假设我们想查找长度小于3的字符串:
void test() {vector<string> sVec{ "sadaw","srfafas","12" };int count = count_if(sVec.begin(), sVec.end(), LessThanLenFunctor(3));//寻找容器中长度小于3的字符串的数量
}
我们只需要传入一个内部成员变量len
为3的仿函数对象就行了,无论长度如何变化,有多少人要使用多少个不同的仿函数,你的仿函数的功能都不会发生变化
它既能像普通函数一样传入给定数量的参数(一个或者多个),还能存储我们需要的控制信息
C++中的仿函数functor相关推荐
- c语言 谓词,C++ 谓词(predicate) 与 仿函数 ( functor (function object))
#谓词与函数对象 谓词 predicate C++ 标准定义谓词如下: The Predicate parameter is used whenever an algorithm expects a ...
- c++仿函数 functor
https://www.cnblogs.com/decade-dnbc66/p/5347088.html 内容整理自国外C++教材 先考虑一个简单的例子:假设有一个vector<string&g ...
- 2022-1-19 C++STL—— 仿函数 functor
仿函数是为了算法而服务的. 我的理解是,相较于函数,仿函数能够实现泛型参数. 如果一个 class 里面重载小括号,这样的函数创建出来的对象就叫做函数对象. 如果想要自己写出的 functor 和 S ...
- 【转】C++中如何区分构造函数与重载operator()得到的仿函数?
转自:C++中如何区分构造函数与重载operator()得到的仿函数?求大神!_360问答 此外,你觉得仿函数(functor)是否能完全取代function呢? 以下是个人使用C++仿函数,func ...
- C++新特性探究(9.1):functor仿函数探究
相关博文:C++新特性探究(九):functor仿函数 Functor 对象模拟函数 把类对象,像函数名一样使用. 仿函数(functor),就是使一个类的使用看上去像一个函数.其实现就是类中 ...
- C++ functor 仿函数
在C++中,仿函数不是一个函数,是一个类,这个类实现了函数的功能. 如果我想实现一个求和的功能:定义一个Sum类,让其中的()函数实现这个功能,代码如下: class Sum { public:Sum ...
- C++多线程并发中线程管理
一.何为并发 刚开始接触计算机编程语言时,我们编写一个程序,在main入口函数中调用其它的函数,计算机按我们设定的调用逻辑来执行指令获得结果.如果我们想在程序中完成多个任务,可以将每个任务实现为一个函 ...
- C++11中的std::function
文章转载自:http://www.jellythink.com/archives/771 看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard ...
- STL学习笔记(仿函数)
仿函数(Functors) 仿函数(functor),就是使一个类的使用看上去象一个函数.其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了. 例如我们定义一个 ...
最新文章
- PL/SQL 中Returning Into的用法
- 用PyCharm Profile分析异步爬虫效率
- easyui不同的jsp页面之间混乱_16.jsp九大内置对象,四大作用域
- 手把手教你做产品经理,视频课教程已经发布,欢迎观看
- xmind-HTTP协议
- STM8单片机ADC单次采样模式
- python编程(supervisor程序管理)
- yml 后面的配置覆盖前面的
- 解决vue项目在ie浏览器缓存问题。
- 配置iSCSI部署网络存储
- 【SimpleITK】胸部CT数据3D space归一化,以及3D plot
- 蓝桥杯2020年第十一届C++省赛第六题-成绩统计
- js实现视频截图,并通过post请求发送图片
- 关于AXD调试的详细探索
- PS教程证件照底片更换颜色
- 2014中秋节,用java为QQ游戏美女找茬写辅助
- onlyoffice修改logo图标及开启https
- stream根据某个字段去重(对象的某个字段去重)
- 排列组合之插板法及变形
- API安全(二):API安全设计原则
热门文章
- 微服务和分布式的联系与区别什么?
- 关于苹果iOS应用审核4.3打回的解决方法
- SOHO帮客户找新品,如何拿到最优价?要不要选择大型机械类产品?
- 题解 | #字符串操作之substring_index提取#
- Android 安装包优化开启资源压缩
- AutoJs制作简易自动化脚本(持续更新)
- TagName的使用
- Invalid tag name “@vue-cli“: Tags may not have any characters that encodeURIComponen 解决
- Linux 内核交互图
- iOS--在应用内切换语言