标签(空格分隔): c++STL
Function object的概念
就是一个定义了operator()的对象;
class FunctionOjbectType{
public:
void operator()(){
//statements
}
};
FunctionObjectType fo;
fo(); //调用的fo对象的operator()
优点:
- function object 比一般函数灵巧,可以拥有状态;同样的函数对象类可以拥有不同的实例;
- 每个函数对象由类型;因此可以将函数对象的类型当做模板参数传递;容器也可以因为不同的函数对象不同而不同;
- 执行速度上,函数对象比函数指针快;
1 以函数对象为排序准则
例如:使用函数对象类为容器排序;
template < class T, // set::key_type/value_type
class Compare = less<T>, // set::key_compare/value_compare
class Alloc = allocator<T> // set::allocator_type
> class set;
set容器提供默认排序为less<T>
类,可以自定义:
class FunctionOjbectType{
public:
void operator()(){
//statements
}
};
set<Myclass, FunctionObjectType> p; //函数对象为排序规则
2 FUnction object 拥有内部状态
通过给函数对象传递参数改变状态:
- 值传递
- 引用传递
传递参数都是通过构造函数传递;
class FunctionOjbectType{
public:
FunctionOjbectType(Args .. args){
//statements
}
void operator()(){
//statements
}
};
3 for_each()的返回值
for_each可以传回其函数对象,因此可以通过for_each的返回值获取函数对象的状态;
template<class InputIterator, class Function>
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;
原因:
template<typename ForwIter, 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成员函数;