# 十、STL函数对象---函数对象的概念

标签(空格分隔): c++STL


Function object的概念

就是一个定义了operator()的对象;

class FunctionOjbectType{
public:
    void operator()(){
        //statements
    }
};

FunctionObjectType fo;
fo();  //调用的fo对象的operator()

优点:

  1. function object 比一般函数灵巧,可以拥有状态;同样的函数对象类可以拥有不同的实例;
  2. 每个函数对象由类型;因此可以将函数对象的类型当做模板参数传递;容器也可以因为不同的函数对象不同而不同;
  3. 执行速度上,函数对象比函数指针快;

1 以函数对象为排序准则

例如:使用函数对象类为容器排序;

template < class T,                        // set::key_type/value_type
           class Compare = less,        // set::key_compare/value_compare
           class Alloc = allocator      // set::allocator_type
           > class set;

set容器提供默认排序为less类,可以自定义:

class FunctionOjbectType{
public:
    void operator()(){
        //statements
    }
};

set p; //函数对象为排序规则

2 FUnction object 拥有内部状态

通过给函数对象传递参数改变状态:

  • 值传递
  • 引用传递
    传递参数都是通过构造函数传递;
class FunctionOjbectType{
public:
    FunctionOjbectType(Args .. args){
    //statements
    }
    void operator()(){
        //statements
    }
};

3 for_each()的返回值

for_each可以传回其函数对象,因此可以通过for_each的返回值获取函数对象的状态;

template
  Function for_each(InputIterator first, InputIterator last, Function fn)
{
  while (first!=last) {
    fn (*first);
    ++first;
  }
  return fn;      // or, since C++11: return move(fn);
}

例子:

class MeanValue{
public:
    int num;
    int sum;
    MeanValue():num(0),sum(0){}
    void operator()(int elem){
        ++num;
        sum += elem;
    }

    double value(){
        return static_cast<double>(sum)/static_cast<double>(num);
    }
};
//-----------省略--------------
vector<int> v={1,2,3,4,5,6};

MeanValue mv = for_each(v.begin(),v.end(),MeanValue());

4 predicate (判断式)和function object(函数对象)

  • predictate: 返回boolean值的函数或者函数对象
  • 对stl而言,并非所有boolean值的函数都是合法的predictate;
    例子:
class rm{
public:
    int count;
    int nth;
    rm(int n) :count(0), nth(n){
    }
    bool operator()(int n){
        return ++count == nth;
    }
};
//--------------省略----------
    vector<int> v = {1,2,3,4,5,6,7,8,9};
    vector<int>::iterator it,iter;
    it = remove_if(v.begin(), v.end(), rm(3));
    for (iter = v.begin(); iter != it; ++iter)
        cout << *iter<<" ";

结果为:

1 2 4 5 7 8 9

缺少了3和6;
原因:

templateForwIter, typename Predicate>
ForwIter remove_if(ForwIter beg, ForwIter end,Predicate op)
{
    beg = find_if(beg,end,op);
    if(beg==end)
        return beg;
    else{
        ForwIter next = beg;
        return remove_copy_if(++next,end,beg,op);
    }

}

这个算法使用find_if查找被移除的第一个元素,然后,使用传入的predicate处理剩下的元素,这个时候原始的Nth再次被使用;就会移除第六个元素;

【注意:】为了考虑不该依赖任何实现细节,应该总是将predicate的operator()声明为const成员函数;

你可能感兴趣的:(stl)