点击查看Evernote原文。
#@author: gr
#@date: 2014-08-13
#@email: forgerui@gmail.com
在stl中,函数对象被大量地使用,用以提高代码的通用性及效率。stl也提供了一些常用的函数对象类型。
###stl学习
|--迭代器
|--类属算法
|--容器
|--vector
|--deque
|--list
|--set
|--map
|--函数对象
|--适配器
|--分配器
一、Contents
1. 所谓函数对象
函数对象是行为类似函数的对象。一个类对象,表现出一个函数的特征,即通过对象名+(参数列表)
的方式使用一个类对象。
2. 初见函数对象
int sum = add(a, b)
可以看做是调用add函数或者使用函数对象,如下:
//1. 完全可以看做是调用add函数
int sum = add(a, b);
//2. 当然也可以看作是使用函数对象,可以通过如下的定义:
Template <class T>
class Add{
public:
T operator() (T a, T b){
return a + b;
}
};
Sum<int> add;s
int sum = add(a, b);
3. 为何要使用函数对象
那么为什么不使用更简单的函数,而选择看起来更复杂的函数对象呢?
在一些情况下,为了使程序富于变化,增加程序的通用性,有时需要将函数当作参数传递,这就需要使用函数指针。
stl类属算法中有一个accumulate函数,其中需要传递一个函数。如下:
//accumulate函数实现,最后一个参数是函数指针
template<typename InputIterator, typename T>
T accumulate(InputIterator first, InputIterator last, T init, T (*binary_function)(T a, T b)){
while(first != last){
init = binary_function(init, *first++);
}
return init;
}
//声明的函数
int product(int a, int b){ return a*b;}
int main(){
int arr[] = {1, 3, 5, 2, 1};
vector<int> vec(arr, arr+6);
//传递声明的函数指针
int product = accumulate(vec.begin(), vec.end(), 1, &product);
}
这样的实现有个问题是通用性不强。函数指针原型可以写为
T (*binary_function) (T a, T b);
这样的函数可以和int product(int, int)
匹配,但如果T类型很大,为了提高效率,需要将上面的语句写为如下:
T (*binary_function) (const T& a, const T& b);
则product将**无法与之匹配××,此时必须将函数重写为
int product(const int&, const int&);
另外一个问题在于效率,必须通过指针才能调用这个函数,所以无法使用内联的方式,如果要执行的函数很小,进行一次函数调用将会有相对大的额外开销,而如果这个函数调用是在一个循环中,可以想象出其对效率有严重的影响。
4. 使用函数对象解决问题
现在修改accumulate函数,使用函数对象作为参数。
template <typename InputIterator, typename T, typename FunObj>
T accumulate(InputIterator first, InputIterator last, T init, FunObj obj){
while(first != last){
init = obj(init, *first++);
}
return init;
}
使用这种定义的优点是,可以传递各式各样的类对象,并且可以对operator()
进行重载,以匹配多种类型的函数调用,而函数指针则只能接受指定类型的函数,这无疑提高了通用性。
另外,编译器可以对operator()
进行内联,从而取消调用函数的开销。
More,使用类对象可以提供额外信息,类对象可以有数据成员,可以记录一些状态,这样可以本地封装信息,而无需采用静态或全局数据来实现...
5. stl中提供的函数对象类
- 算术运算类
plus
,minus
,multiplies
,divides
,modules
,negate
- 比较运算
equal_to
,not_equal_to
,greater
,less
,greater_equal
,less_equal
- 逻辑运算
logical_and
,logical_or
,logical_not
二、Miscellany
@author gr
@mail forgerui@gmail.com