仿函数:是一个定义了operator()的对象(即重载了括号运算符),可以将它视为一般的函数。但它与一般函数的区别是其功能是在其成员函数operator()中定义,主要具有以下三个优点:
(1)比一般的函数灵活,应为仿函数拥有状态(即有成员变量做数据的记录);
(2)仿函数型别可以作为模板参数;
(3)仿函数要比函数指针的执行速度要快;
仿函数的三个概念:生成器,一元函数,二元函数。
生成器:即无参仿函数;
一元函数:用一个形参就可以调用的仿函数;
二元函数:用两个形参才可以调用的仿函数;
仿函数的通常的4种作用:
(1)作为排序规则;
(2)拥有内部状态(利用成员变量记录信息)--(例如第2和第3点的举例);
(3)在for_each算法中可以返回值;(例如第4点的举例)
(4)作为判断式;(例如第5点的举例)
以下的例子中会分别指出这三个概念。
1.利用仿函数写一个通用的数组求和算法,只要修改仿函数还可以轻松的实现其他的功能
#include<iostream>
#include<algorithm>
using namespace std;
template <typename InputIterator, typename T, typename FunObject>
inline T accumulate(InputIterator first, InputIterator last, T init, FunObject object)//仿函数做参数
{//函数对象
while (first != last)
{
init = object(init, *first);//关键部分
++first;
}
return init;
}
template < typename T>//仿函数模板
class Test
{
public:
T operator()(const T& x, const T& y)
{
return x + y;
}
};
void main(void)
{
int a[5] = { 2, 5, 7, 9, 11 };
Test <int> t;
random_shuffle(&a[0], &a[5]);
int x = ::accumulate(&a[0], &a[5], 0, Test<int>());
cout << x << endl;
system("pause");
}
2.利用仿函数向容器中插入想要的序列利用算法genrate_n或genrate
void out(list<int><)//遍历并且输出list<int>中的元素
{
list<int>::iterator it;
for (it = lt.begin(); it != lt.end(); it++)
{
cout << *it << "," ;
}
cout << endl;
}
class sequence
{
private:
int value;
public:
sequence(int v) :value(v){};
int operator ()(void)
{
return value++;
}
};
void main()
{
list<int>l1;
generate_n(back_inserter(l1), 9, sequence(1));//名为产生算法,用于产生数值(利用仿函数产生)并向集群内插入;back_inserter(容器)容器插入迭代器
out(l1);
generate(++l1.begin(), --l1.end(), sequence(11));//和generate_n类似
out(l1);
system("pause");
}
1,2,3,4,5,6,7,8,9,
1,11,12,13,14,15,16,17,9,
3.在转换算法tranfrom中使用仿函数
#include<iostream>
#include<string>
#include<algorithm>
#include<list>
using namespace std;
template<class T>
void print(T &ele)
{
cout << ele << ", ";
}
template <class T>
class function1
{
public:
T parm;
public:
function1(T p) :parm(p){}
T operator ()(T&ele)const
{
return ele*parm;
}
};
template <class T>
class function2
{
public:
T parm;
public:
function2(T p) :parm(p){}
T operator ()(T &ele,T &ele2)const
{
return (ele+ele2)*parm;
}
};
void main()
{
int b[] = { 1, 3, 5, 7, 9, 11, 13, 15, 17 };
list<int>l1, l2;
generate_n(back_inserter(l1), 9, sequence(1));//sequence为上面定义过的
copy(b, b + 9, back_inserter(l2));
for_each(l1.begin(), l1.end(), print<int>);//使用了for_each算法
cout << endl;
copy(l2.begin(), l2.end(), ostream_iterator<int>(cout, ","));//第三个参数为指向标准输出流的指针
cout << endl;
transform(l1.begin(), l1.end(), l1.begin(), function1<int>(2));//转换算法,利用仿函数function1规则对容器l1进行转换,并从l1.begin()开始存入其中
for_each(l1.begin(), l1.end(), print<int>);
cout << endl;
transform(l2.begin(), l2.end(), l2.begin(), l2.begin(), function2<int>(4)); //利用仿函数function2规则对容器l2进行转换(注意该仿函数有两个参数)
for_each(l2.begin(), l2.end(), print<int>);
cout << endl;
system("pause");
}
结果
1, 2, 3, 4, 5, 6, 7, 8, 9,
1,3,5,7,9,11,13,15,17,
2, 4, 6, 8, 10, 12, 14, 16, 18,
8, 24, 40, 56, 72, 88, 104, 120, 136,
4.算法each_for()可以返回仿函数而不必实例化“引用计数版本”
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
class average
{
private:
long num; long sum;
public:
average() :num(0), sum(0){};
void operator ()(int elem)
{
num++;
sum += elem;
}
double aver()
{
return static_cast<double>(sum*1.0 / num);
}
};
class sequence
{
private:
int value;
public:
sequence(int v) :value(v){};
int operator ()(void)
{
return value++;
}
};
void main()
{
vector<int>v;
generate_n(back_inserter(v), 4, sequence(1));
copy(v.begin(), v.end(), ostream_iterator<int>(cout, ","));
average av = for_each(v.begin(), v.end(), average());
cout << av.aver() << endl;
system("pause");
}
结果
1,2,3,4,
average:2.5
请按任意键继续. . .
5.判断式可以返回仿函数的
#include<iostream>
#include<string>
#include<algorithm>
#include<list>
using namespace std;
void out(list<int>lt)//遍历并且输出list<int>中的元素
{
list<int>::iterator it;
for (it = lt.begin(); it != lt.end(); it++)
{
cout << *it << ",";
}
cout << endl;
}
class succeed
{
private:
int num; int count;
public:
succeed(int n) :num(n), count(0){};
bool operator ()( int) const
{
static int n = count;
return (++n == num);
}
};
class sequence
{
private:
int value;
public:
sequence(int v) :value(v){};
int operator ()(void)
{
return value++;
}
};
void main()
{
list<int> l1;
generate_n(back_inserter(l1), 8, sequence(1));
out(l1);
list<int>::iterator pr;
pr = remove_if(l1.begin(), l1.end(), succeed(3));
l1.erase(pr, l1.end());
out(l1);
system("pause");
}
结果:
1,2,3,4,5,6,7,8,
1,2,4,5,6,7,8,
请按任意键继续. . .
.
可以参考:http://blog.csdn.net/ggz631047367/article/details/38058245
待更新。。。。。。。