STL(八):函数对象、 函数对象与容器、函数对象与算法
来源:互联网 发布:怎么下载word2010软件 编辑:程序博客网 时间:2024/05/18 00:00
一、函数对象
1、函数对象(function object)也称为仿函数(functor)
2、一个行为类似函数的对象,它可以没有参数,也可以带有若干参数。
3、任何重载了调用运算符operator()的类的对象都满足函数对象的特征
4、函数对象可以把它称之为smart function。
5、STL中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类。为了调用这些标准函数对象,需要包含头文件<functional>。
二、自定义函数对象
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using namespace std;
class CFunObj
{
public:
void operator()()
{
cout << "hello,function object!" << endl;
}
};
int main()
{
CFunObj fo;
fo();
CFunObj()();
return 0;
}
注意:CFunObj()(); 表示先构造一个匿名对象,再调用operator();
三、函数对象与容器
在这边举map 容器的例子,大家都知道map 在插入元素的时候会自动排序,默认是根据key 从小到大排序,看map 的定义:
2
3
4
5
6
7
8
9
10
template < class _Kty,
class _Ty,
class _Pr = less<_Kty>,
class _Alloc = allocator<pair<const _Kty, _Ty> > >
class map
: public _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, false> >
{
// ordered red-black tree of {key, mapped} values, unique keys
};
假设现在我们这样使用 map< int, string > mapTest; 那么默认的第三个参数 _Pr = less<int>,再者,map 继承的其中一个类
_Tmap_traits 中有个成员:
_Pr comp;// the comparator predicate for keys
跟踪进insert 函数,其中有这样一句:
if (_DEBUG_LT_PRED(this->comp, _Key(_Where._Mynode()), this->_Kfn(_Val)))
已知 #define _DEBUG_LT_PRED(pred, x, y) pred(x, y) 很明显地,comp 在这里当作函数对象使用,传入两个参数,回头看less 类的
模板实现:
2
3
4
5
6
7
8
9
10
11
12
13
template<class _Ty>
struct less
: public binary_function<_Ty, _Ty, bool>
{
// functor for operator<
bool operator()(const _Ty &_Left, const _Ty &_Right) const
{
// apply operator< to operands
return (_Left < _Right);
}
};
即实现了operator() 函数,左操作数小于右操作数时返回为真。
我们也可以在定义的时候传递第三个参数,如map< int, string, greater<int> > mapTest; 则插入时按key 值从大到小排序(less,
greater 都是STL内置的类,里面实现了operator() 函数),甚至也可以自己实现一个类传递进去,如下面例程所示:
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
#include <string>
#include <iostream>
using namespace std;
struct MyGreater
{
bool operator()(int left, int right)
{
return left > right;
}
};
int main(void)
{
map < int, string, /*greater<int> */MyGreater > mapTest;
mapTest.insert(map<int, string>::value_type(1, "aaaa"));
mapTest.insert(map<int, string>::value_type(3, "cccc"));
mapTest.insert(map<int, string>::value_type(2, "bbbb"));
for (map < int, string, /*greater<int> */MyGreater >::const_iterator it = mapTest.begin(); it != mapTest.end(); ++it)
{
cout << it->first << " " << it->second << endl;
}
return 0;
}
输出为:
3 cccc
2 bbbb
1 aaaa
MyGreater 类并不是以模板实现,只是比较key 值为int 类型的大小。
四、函数对象与算法
在STL一些算法中可以传入函数指针,实现自定义比较逻辑或者计算,同样地这些函数也可以使用函数对象来代替,直接看例程再稍
作分析:
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
void PrintFun(int n)
{
cout << n << ' ';
}
void Add3(int &n)
{
n += 3;
}
class PrintObj
{
public:
void operator()(int n)
{
cout << n << ' ';
}
};
class AddObj
{
public:
AddObj(int number) : number_(number)
{
}
void operator()(int &n)
{
n += number_;
}
private:
int number_;
};
class GreaterObj
{
public:
GreaterObj(int number) : number_(number)
{
}
bool operator()(int n)
{
return n > number_;
}
private:
int number_;
};
int main(void)
{
int a[] = {1, 2, 3, 4, 5};
vector<int> v(a, a + 5);
/*for_each(v.begin(), v.end(), PrintFun);
cout<<endl;*/
for_each(v.begin(), v.end(), PrintObj());
cout << endl;
/*for_each(v.begin(), v.end(), Add3);
for_each(v.begin(), v.end(), PrintFun);
cout<<endl;*/
for_each(v.begin(), v.end(), AddObj(5));
for_each(v.begin(), v.end(), PrintFun);
cout << endl;
cout << count_if(a, a + 5, GreaterObj(3)) << endl; //计算大于3的元素个数
return 0;
}
输出为:
1 2 3 4 5
6 7 8 9 10
2
回顾for_each 的源码,其中有这样一句: _Func(*_ChkFirst); 也就是将遍历得到的元素当作参数传入函数。
上面程序使用了函数对象,实际上可以这样理解 PrintObj()(*_ChkFirst); 即 PrintObj() 是一个匿名的函数对象,传入参
数,调用了operator() 函数进行打印输出。使用函数对象的好处是比较灵活,比如直接使用函数Add3,那么只能将元素加3,而
使用函数对象Addobj(x), 想让元素加上多少就传递给Addobj类,构造一个对象即可,因为它可以保存一种状态(类成员)。
count_if 中的 GreaterObj(3) 就类似了,将遍历的元素当作参数传递给operator(), 即若元素比3大则返回为真。
五、STL内置的函数对象类
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
- C++之STL(八):函数对象、 函数对象与容器、函数对象与算法
- STL(八):函数对象、 函数对象与容器、函数对象与算法
- 从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法
- 从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法
- 从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法
- STL算法--------函数对象
- STL算法--函数对象
- STL算法和函数对象
- STL算法和函数对象
- 仿函数(函数对象)和STL算法
- 函数对象与函数指针
- 函数对象与函数指针
- 函数对象与函数指针
- 函数对象与Lambda
- javascript 函数与对象
- 函数与内置对象
- javascript函数与对象
- OC对象与函数
- Github Git Cheat Sheet
- PB中取得数据窗口所有列名以及列标题名称
- QuickContactBadge去掉三角
- STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)
- OC利用类别对类进行模块化设计和使用类别来调用私有方法
- STL(八):函数对象、 函数对象与容器、函数对象与算法
- 高级指针的应用
- python 读取CSV 文件
- 《快来看一只老鼠下了13只小老鼠》
- STL(九):函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例
- cocos2dx 3.2版本获得精灵缩放后的尺寸大小
- 你理解我的意思么?
- 中国顶级黑客的生意—---在商业利益与社会责任间两难抉择
- STL(十):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}