Functor仿函数
转载声明:本文转自网络,稍加整理以备学习和參考之用。
函数对象/仿函数
Object,JJHou译作Functor仿函数)。
什么是函数对象
顾名思义,函数对象首先是一个对象,即某个类的实例。
其次,函数对象的行为和函数一致,即是说能够像调用函数一样来使用函数对象,如參数传递、返回值等。
这样的行为是通过重载类的()操作符来实现的,
仿函数:用途和适用的场合
之所以要开发仿函数(functors),是由于函数不能容纳不论什么有意义的状态。
比如。使用函数,你不能为某个元素加一个随意值。再将其应用于一个范围。可是,使用仿函数可轻易做到这一点。
#include <iostream> #include <algorithm> using namespace std; //回调函数 void call_back( char elem) { cout << elem << endl; } //仿函数 struct Functor { void operator() ( char elem) { cout << elem << endl; } }; int main() { string strA = "hello" ; string strB = "world" ; for_each(strA.begin(),strA.end(),Functor()); cout<< "===========GAP===============" <<endl; for_each(strB.begin(),strB.end(),call_back); getchar (); return 0; } |
h
e
l
l
o
===========GAP===============
w
o
r
l
d
可能会有疑问两者有什么差别?
假如我要for_each遍历的不是字符串而是int类型的vector呢?
是不是又要重写一个int类型作为參数的回调函数,那假设有N种类型的容器遍历岂不是要写N个回调函数或N个仿函数类?
非也!!!
C++有类模板 也有 函数模板 相同能够用于回调
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
#include <iostream> #include <algorithm> #include <vector> using namespace std; //模板函数 template < typename T> void call_back(T elem) { cout<< elem <<endl; } //仿函数 template < typename T> class Functor { public : Functor() :m_val(0) { cout<< "Functor()" <<endl; } ~Functor() { cout<< "~Functor()" <<endl; } void operator() (T elem) { Do(elem); } //举个栗子 void Do(T elem) { m_val+=elem; cout<<elem<< "/" <<m_val<<endl; } private : T m_val; }; int main() { vector< int > vec; vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); for_each(vec.begin(),vec.end(),call_back< int >); cout<< "===========GAP===============" <<endl; for_each(vec.begin(),vec.end(),Functor< int >()); return 0; } |
1
2
3
4
5
===========GAP===============
Functor()
1/1
2/3
3/6
4/10
5/15
~Functor()
~Functor()
~Functor()
三次析构的原因:
先附上for_each的源代码(VC2008)
1
2
3
4
5
6
7
8
9
10
11
|
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); _CHECKED_BASE_TYPE(_InIt) _ChkFirst(_CHECKED_BASE(_First)); _CHECKED_BASE_TYPE(_InIt) _ChkLast(_CHECKED_BASE(_Last)); for (; _ChkFirst != _ChkLast; ++_ChkFirst) _Func(*_ChkFirst); return (_Func); } |
1
2
3
4
5
|
Functor<int>() 产生暂时对象传參(值) 构造一次,析构一次 for_each參数值传递,拷贝构造一次,析构一次(函数内部) for_each返回仿函数的对象(值),拷贝构造一次,析构一次 由于没有重载拷贝构造函数 所以打印出第一次创建暂时对象时的普通构造函数 实际上在这个过程中一共产生过三个仿函数对象 |
假设把代码改变下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
#include <iostream> #include <algorithm> #include <vector> using namespace std; template < typename T> class Functor { public : Functor() :m_val(0) { cout<< "Functor()" << this <<endl; } Functor(Functor& that) { this ->m_val = that.m_val; cout<< "Copy Functor()" << this <<endl; } ~Functor() { cout<< "~Functor()" << this <<endl; } void operator() (T elem) { Do(elem); } //举个栗子 void Do(T elem) { m_val+=elem; cout<<elem<< "/" <<m_val<<endl; } T getVal() { return m_val; } private : T m_val; }; int main() { vector< int > vec; vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); Functor< int > func; Functor< int >& ref = for_each(vec.begin(),vec.end(),func); cout<< ref .getVal()<<endl; return 0; } |
执行结果
Functor()0032F800 //main函数中的实參仿函数对象
Copy Functor()0032F68C //值传递 对【实參对象】拷贝构造了形參对象
1/1
2/3
3/6
4/10
5/15
Copy Functor()0032F7E8 //返回对象的值类型 对【形參对象】拷贝构造
~Functor()0032F68C //析构形參对象
15
~Functor()0032F7E8 //析构返回值对象
~Functor()0032F800 //析构实參对象
如今一目了然了吧!
使用回调函数高效 由上面的样例能够看出 构造1次 拷贝构造2次 析构3次 是有代价的
最后回到仿函数和回调函数
差别在于:
使用仿函数能够声明在业务相关的类内部 缩小作用域
使用仿函数能够使用类的成员属性和成员函数
仿函数是一个类 能够使用面向对象的各种机制(封装
继承 多态)若使用回调函数 那么仅仅能声明为某个类的静态成员函数或全局函数。使用类内部的资源须要用一些手段传參,没有直接使用成员函数便捷
Functor仿函数的更多相关文章
- 仿函数(二、stl中常用仿函数)
提到C++ STL,首先被人想到的是它的三大组件:Containers, Iterators, Algorithms,即容器,迭代器和算法.容器为用户提供了常用的数据结构,算法大多是独立于容器的常用的 ...
- js Functor Copy
原文地址:https://segmentfault.com/a/1190000006051586?utm_source=tuicool&utm_medium=referral 本处仅仅个人存档 ...
- Java基础常见英语词汇
Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的 ['prəʊɡræmɪŋ]编程 OO: object ...
- IT软件开发常用英语词汇
Aabstract 抽象的abstract base class (ABC)抽象基类abstract class 抽象类abstraction 抽象.抽象物.抽象性access 存取.访问access ...
- computer English
算法常用术语中英对照Data Structures 基本数据结构Dictionaries 字典PriorityQueues 堆Graph Data Structures 图Set Data Struc ...
- IT软件开发中常用的英语词汇
Aabstract 抽象的abstract base class (ABC)抽象基类abstract class 抽象类abstraction 抽象.抽象物.抽象性access 存取.访问access ...
- 整理C++面试题for非CS程序猿——更新至【48】
结合网上的C++面试题+自己的面经,进行整理记录,for我这种非CS的程序猿.(不定期更新,加入了自己的理解,如有不对,请指出) [1] new/delete和malloc/free的区别和联系? 1 ...
- 看到了必须要Mark啊,最全的编程中英文词汇对照汇总(里面有好几个版本的,每个版本从a到d的顺序排列)
java: 第一章: JDK(Java Development Kit) java开发工具包 JVM(Java Virtual Machine) java虚拟机 Javac 编译命令 java ...
- php英语单词大全95
abstract抽象的 -挨伯丝拽克特 access存取.访问 -挨克色丝 account账户 -厄靠恩特 action动作 -爱克身 activate激活 -爱克特维特 active活动的 -爱克得 ...
随机推荐
- js数组基础整理
首页: 主要整理了一下数组中常用的一些基础知识,代码都是自己手敲,有不对的地方希望能指出,目前只有4篇,后续会不断的增加这一板块. 由于少于100字不能发所以把一些最基本的创建数组也写上. // 创建 ...
- 设置MyEclipse中代码的换行长度
1.打开Preferences -> Java -> Code Style -> Formatter. 2.选择Edit -> Line Wrapping -> Max ...
- Hadoop2.0/YARN深入浅出(Hadoop2.0、Spark、Storm和Tez)
随着云计算.大数据迅速发展,亟需用hadoop解决大数据量高并发访问的瓶颈.谷歌.淘宝.百度.京东等底层都应用hadoop.越来越多的企 业急需引入hadoop技术人才.由于掌握Hadoop技术的开发 ...
- 第五天学习内容 for循环,嵌套
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- 基于visual Studio2013解决面试题之0402合并升序链表并去重
题目
- 网页class命名规范
CSS样式命名整理 页面结构 容器: container/wrap 总体宽度:wrapper 页头:header 内容:content 页面主体:main 页尾:footer 导航:nav 側栏:si ...
- 友情转发一则Erlang招聘广告
新锐手游开发公司WalkYY,招聘Erlang游戏服务端开发工程师若干名,要求有半年以上Erlang游戏服务端开发经验,熟悉Erlang OTP和MySQL数据库.公司团队靠谱,发展空间大,有意者请发 ...
- 基于FPGA的红外遥控解码与PC串口通信
基于FPGA的红外遥控解码与PC串口通信 zouxy09@qq.com http://blog.csdn.net/zouxy09 这是我的<电子设计EDA>的课程设计作业(呵呵,这个月都拿 ...
- HDU1849 Rabbit and Grass()
用异或看取得的值是否为0推断 思想换没搞懂 #include<stdio.h> int main() { int ans,n,a; while(scanf("%d",& ...
- 搜索引擎爬虫蜘蛛的USERAGENT大全
搜索引擎爬虫蜘蛛的USERAGENT大全 搜索引擎爬虫蜘蛛的USERAGENT收集,方便制作采集的朋友. 百度爬虫 * Baiduspider+(+http://www.baidu.com/sea ...