顾名思义,函数对象首先是一个对象,即某个类的实例。其次,函数对象的行为和函数一致,即是说可以像调用函数一样来使用函数对象,如参数传递、返回值等。这种行为是通过重载类的()操作符来实现的,
#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次 是有代价的
最后回到仿函数和回调函数
区别在于:
使用仿函数可以声明在业务相关的类内部 缩小作用域
使用仿函数可以使用类的成员属性和成员函数
仿函数是一个类 可以使用面向对象的各种机制(封装 继承 多态)
若使用回调函数 那么只能声明为某个类的静态成员函数或全局函数,使用类内部的资源需要用一些手段传参,没有直接使用成员函数便捷
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/wstzone/article/details/46714643