###STL学习--函数对象

点击查看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
posted @ 2014-09-15 16:42  bairuiworld  阅读(318)  评论(0编辑  收藏  举报