什么是仿函数
答:仿函数又叫函数对象,是一个定义了operator()的对象。你可以将仿函数视为一般函数,只不过不是将所有语句放在函数体里,而是放在operator()中撰写。
//例如
struct foo
{
void operator()(int i)
{
cout << i;
}
};
int main()
{
int a[5] = { 1,2,3,4,5 };
foo f;
for (int i = 0; i < 5; i++)
f(a[i]);
}
//输出12345
仿函数与一般函数相比优点在哪?
1:仿函数比一般函数更灵活,因为它可以有不同的状态。
2:每个仿函数都有其型别,所以我们可以将其当作模板参数来传递
3:执行速度上,仿函数通常比一般函数更快
//这里将展示 仿函数比一般函数更灵活的例子
//我们定义了一个仿函数和一个一般函数,让它们判断参数是否大于3
class foo
{
private:
int value;
public:
foo(int v = 0) :value(v) {}
bool operator()(int i)
{
return i > value;
}
};
bool fx(int i)
{
return i > 3;
}
int main()
{
int a[5] = { 1,2,3,4,5 };
for (int i = 0; i < 5; i++)
{
if (fx(a[i]))
cout << a[i] << " ";
}cout << endl;
for (int i = 0; i < 5; i++)
{
//foo(3)(a[i])
//等价于 foo f(3)
// f(a[i])
if (foo(3)(a[i]))
cout << a[i] << " ";
}cout << endl;
//如果我们将判断条件改成是否大于2
for (int i = 0; i < 5; i++)
{
if (foo(2)(a[i]))
cout << a[i] << " ";
}cout << endl;
}
//我们可以很清楚的感受到仿函数比一般函数更灵活
//如果是一般函数只能在函数体修改判断条件
需要注意的一点是,仿函数以by value的方式传递,这样做的好处是你可以传递常量或者临时表达式。缺点是:你无法改变仿函数的状态,利用for_each()可以帮助我们保存仿函数的状态
//我们可以利用for_each()的返回值来保存仿函数的状态(value的值)
class foo
{
private:
int value;
public:
foo(int v = 0) :value(v) {}
void operator()(int& i)
{
i+=value;
value++;
}
};
int main()
{
vector<int>c1 = { 1,2,3 };
vector<int>c2 = { 1,2,3 };
foo fx=for_each(c1.begin(), c1.end(), foo(2));
for (auto e : c1) //3 5 7
cout << e << ' ';
cout << endl;
for_each(c2.begin(), c2.end(), fx);
for (auto e : c2) //6 8 10
cout << e << ' ';
cout << endl;
}
C++标准库预定义的仿函数
使用时需要包含头文件functional
表达式 | 功能 |
---|---|
negate<>() | -x |
plus<>() | x1+x2 |
minus<>() | x1-x2 |
multiplies<>() | x1*x2 |
divides<>()) | x1/x2 |
modulus<>() | x1%x2 |
equal_to<>() | x1 == x2 |
not_equal_to<>() | x1 !=x2 |
less<>() | x1<x2 |
greater<>() | x1>x2 |
less_equal<>() | x1 <= x2 |
greater_equal<>() | x1>=x2 |
logical_not<>() | !x |
logical_and<>() | x1&&x2 |
logical_or<>() | x1 或 x2 |
函数配接器(Function Adapters)
表达式 | 功能 |
---|---|
bind1st(op,value) | 将value绑定为op函数的第一参数 |
bind2dn(op,value) | 将value绑定为op函数的第二参数 |
not1(op) | 将op函数结果取反 ,op为判断函数,接受一个参数 |
not2(op) | 将op函数结果取反 ,op为判断函数,接受两个参数 |
针对成员函数而设计的函数配接器
表达式 | 功能 |
---|---|
mem_fun_ref(op) | 调用op,那是某个对象的一个const成员函数 |
mem_fun(op) | 调用op,那是某个对象指针的一个const成员函数 |
针对一般函数而设计的函数配接器
表达式 | 功能 |
---|---|
ptr_fun(op) | op(x) |
//例如有这样一个一般函数
bool check()
{
.....
}
int main()
{
find_if(c.begin(),c.end(),not1(ptr_fun(check)));
}
如何让自定义的仿函数可以使用函数配接器?
答:使用上述的ptr_fun(),或者让你自定义的仿函数继承unary_function或者binary_function具体继承那个类,取决你的仿函数是一元函数还是二元函数。
辅助用(组合型)的仿函数
答:即一些将几种仿函数结合在一起的函数配接器,我个人认为使用该配接器过于麻烦,可以使用C++11新特性中的lambada表达式来实现我们要的效果。如果该想法有误,请指正。