仿函数与一般函数的优势:
1、仿函数是“smart functions”(智能型函数)
仿函数可以拥有成员函数和成员变量,即仿函数拥有状态。
2、每个仿函数都有自己的型别
每个仿函数有自己的型别。因此,可以将仿函数的型别当做template参数来传递。
从而指定某种行为模式。
3、仿函数通常比一般函数速度快
就template概念而言,由于更多细节在编译期间就已确定,所以通常可能进行更好
的最佳化。所以,传入一个仿函数,可能获得更好的性能。
一、 针对“仿函数拥有属于自己的独特型别”的例子:
class Person
{
public:
std::string getFirstName() const
{
return firstName;
}
std::string getLastName() const
{
return lastName;
}
private:
std::string firstName;
std::string lastName;
};
class PersonSortCriterion
{
public:
bool operator()(const Person& p1, const Person& p2)
{
return p1.getLastName() < p2.getLastName() || (!(p1.getLastName() < p2.getLastName()) && (p1.getFirstName() < p2.getFirstName()));
}
}
int main()
{
typedef std::set<Person,PersonSortCriterion> PersonSet;
PersonSet coll;
}
这里coll使用了特殊排序准则PersonSortCriterion,而它是个仿函数类别,所以可以把
它当做set的template参数。以上述型别作为排序准则的所有sets,都拥有自己的独特型别
(PersonSet)。
二、拥有内部状态的仿函数。
class IntSequence
{
public:
IntSequence(int initialValue):value(initialValue) {}
int operator() ()
{
return ++value;
}
private:
int value;
};
此仿函数拥有内部变量value,称之为IntSequence的内部状态,利用generate算法生成容器内元素时,可发现value的值是变化的。
三、仿函数一般是传值,不是传引用。因此算法不会改变随参数而来的仿函数的状态。
传值的好处:
你可以传递常量和暂时表达式。
但有时候我们需要知道仿函数的状态时,可通过两个办法解决:
1、以by reference的方式传递仿函数。
需要在调用算法时,明白标示仿函数型别是个reference型别。
PS:generate_n<back_inserter_iterator<list<int> >, int, IntSequence&>(back_inserter(coll), 4, seq);
2、用for_each的返回值。
for_each的返回值是仿函数。
四、remove_if算法的问题:
实作代码:
template<class ForwIter, class Predicate >
ForeIter std::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来搜寻第一个元素。然而接下来它使用传进来的判断是op的副本去处理剩余元素。在移除元素的过程中会出现意想不到的错误。
五、函数配接器:
bind1st,bind2st,not1,not2(!op(param1,param2))
针对成员函数设计的函数配接器:
mem_fun_ref(op) :调用op,那是某对象的一个const成员函数。
mem_fun(op) :调用op,那是某对象指针的一个const成员函数。
Note:被mem_fun_ref和mem_fun调用的成员函数必须是const,C++标准程序库并不针对non-const成员函数提供函数配接器。
针对一般函数:
prt_fun(op)。
六、自定义仿函数也使用函数配接器。
你可以编写自己的仿函数,但要求它能够使用函数配接器,就必须满足某些条件:必须提供一些型别成员来反映其参数和返回值的型别。
PS:
template <class T1, class T2 >
class fopow:public std::binary_function<T1, T2 ,T1>
{
public:
T1 operator()(T1 base, T2 exp) const
{
return std::pow(base,exp);
}
};
main中的使用:
std::vector<int> coll2;
for(int i = 0; i<= 9; ++i)
{
coll2.push_back(i);
}
std::transform(coll2.begin(),coll2.end(),std::ostream_iterator<int>(std::cout," "),std::bind1st(fopow<float,int>(),3));
std::transform(coll2.begin(),coll2.end(),std::ostream_iterator<int>(std::cout," s "),std::bind2nd(fopow<float,int>(),3));
七、组合函数配接器
1、op1(op2(x))
实现:
template<class OP1, class OP2>
class compose_f_gx_t : public std::unary_function<typename OP2::argument_type, typename OP1::result_type>
{
public:
compose_f_gx_t(const OP1& o1, const OP2& o2) : op1(o1),op2(o2){}
typename OP1::result_type operator()(const typename OP2::argument_type& x) const
{
return op1(op2(x));
}
private:
OP1 op1; OP2 op2;
};
template <class OP1, class OP2>
inline compose_f_gx_t<OP1,OP2> compose_f_gx(const OP1& o1, const OP2& o2)
{
return compose_f_gx_t<OP1,OP2>(o1,o2);
}
2、op1(op2(x),op3(x)
实现:
template<class OP1, class OP2, class OP3>
class compose_f_gx_hx_t : public std::unary_function<typename OP2::argument_type, typename OP1::result_type>
{
public:
compose_f_gx_hx_t(const OP1& o1,const OP2& o2,const OP3& o3):op1(o1),op2(o2),op3(o3){}
typename OP1::result_type operator() (const typename OP2::argument_type& x) const
{
return op1(op2(x),op3(x));
}
private:
OP1 op1;
OP2 op2;
OP3 op3;
};
template <class OP1, class OP2, class OP3>
inline compose_f_gx_hx_t<OP1,OP2,OP3> compose_f_gx_hx(const OP1& o1, const OP2& o2, const OP3& o3)
{
return compose_f_gx_hx_t<OP1,OP2,OP3>(o1,o2,o3);
}
3、op1(op2(x),op3(y))
template<class OP1, class OP2, class OP3>
class compose_f_gx_hy_t : public std::binary_function<typename OP2::argument_type, typename OP3::argument_type, typename OP1::result_type>
{
public: compose_f_gx_hy_t(const OP1& o1, const OP2& o2, const OP3& o3):op1(o1),op2(o2),op3(o3){}
typename OP1::result_type operator()(const typename OP2::argument_type& x, const typename OP3::argument_type& y) const
{
return op1(op2(x),op3(y));
}
private:
OP1 op1;
OP2 op2;
OP3 op3;
};
template <class OP1,class OP2,class OP3>
inline compose_f_gx_hy_t<OP1,OP2,OP3> compose_f_gx_hy(const OP1& o1, const OP2& o2, const OP3& o3)
{
return compose_f_gx_hy_t<OP1,OP2,OP3>(o1,o2,o3);
}