仿函数的使用

仿函数:是一个定义了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


待更新。。。。。。。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值