c++ STL_5 仿函数

所谓的仿函数,就是定义一个operator()的对象。
仿函数的三个优点:

  1. 仿函数可以拥有成员函数和成员变量。通常如在类中实现的,可以增加其他成员。
  2. 每一个仿函数都有自己的型别。可以进行模板化实现,即实现多个状态。
  3. 仿函数通常快于一般函数,因为通常在编译阶段就完成了许多细节。

示例1:

#include<iostream>
using namespace std;
struct funtion {
	void operator()(int i) {
		cout << "i = " << i << endl;
	}
};
int main()
{
	funtion CPrint;
	CPrint(10);//像函数一样去使用
	CPrint.operator()(10);//显示调用
	return 0;
}

执行效果
在这里插入图片描述
分析
此处就是一般调用的形式。

示例2:

#include<iostream>
#include<list>
#include<algorithm>
#include <iterator>
using namespace std;
typedef list<int> List;
class funtion {
private:
	int value;
public:
	funtion(int v):value(v){ }
	void operator()(int& elem)const {
		elem += value;
		cout << "elem" << elem << endl;
	}
};
int main()
{
	List _list;
	for (int i = 0; i <= 10; i++)
		_list.push_back(i);
	for_each(_list.begin(), _list.end(), funtion(10));
	copy(_list.begin(), _list.end(), ostream_iterator<int>(cout, " "));
	return 0;
}

执行效果
在这里插入图片描述
分析
for_each(_list.begin(), _list.end(), funtion(10));每一个元素加10,这个表达式funtion(10)生出一个funtion物件,并以10作为初值,funtion的构造函数将这个值保存在成员value中。而在for_each()之内,针对_list的每一个元素调用(),实际上就是对传入的那个funtion暂时对象调用operator(),并以容器元素作为参数。仿函数(funtion对象将每一个元素加10处理)。

示例3

#include<iostream>
#include<list>
#include<algorithm>
#include <iterator>
using namespace std;
typedef list<int> List;
class funtion {
private:
	int value;
public:
	funtion(int v):value(v){ }
	void operator()(int& elem)const {
		elem += value;
		cout << "elem" << elem << endl;
	}
};
int main()
{
	List _list;
	for (int i = 0; i <= 10; i++)
		_list.push_back(i);
	funtion a1(10);
	funtion a2(20);
	for_each(_list.begin(), _list.end(), a1);
	copy(_list.begin(), _list.end(), ostream_iterator<int>(cout, " "));
	cout << endl;
	for_each(_list.begin(), _list.end(), a2);
	copy(_list.begin(), _list.end(), ostream_iterator<int>(cout, " "));
	return 0;
}

执行效果
在这里插入图片描述分析
以上实现就是两个不同的仿函数。

最后注意的是,仿函数以传值得方式并不会改变仿函数的状态,此状态指仿函数内部的参数值,如:

#include<iostream>
#include<list>
#include<algorithm>
#include <iterator>
using namespace std;
typedef list<int> List;
class funtion {
private:
	int value;
public:
	funtion(int v):value(v){ }
	int operator()() {
		return value++;
	}
};
int main()
{
	
	List coll;
	funtion a(1);
	//generate_n<back_insert_iterator<list<int> >,int,funtion& >(back_inserter(coll),9,a);
    generate_n(back_inserter(coll), 9, a);
	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
	cout << endl;
	generate(coll.begin(), coll.end(), a);
	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
	return 0;
}

执行效果
在这里插入图片描述
每次调用的时候value的值都不是上次调用时的状态值,而是重新的值,如第二次调用generate(coll.begin(), coll.end(), a);此过程中value的值还是从1开始。

有时候为了继从上一个状态,可以如下实现

#include<iostream>
#include<list>
#include<algorithm>
#include <iterator>
using namespace std;
typedef list<int> List;
class funtion {
private:
	int value;
public:
	funtion(int v):value(v){ }
	int operator()() {
		return value++;
	}
};
int main()
{
	
	List coll;
	funtion a(1);
	generate_n<back_insert_iterator<list<int> >,int,funtion& >(back_inserter(coll),9,a);
   //generate_n(back_inserter(coll), 9, a);
	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
	cout << endl;
	generate(coll.begin(), coll.end(), a);
	copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
	return 0;
}

执行效果
在这里插入图片描述
发现第二次是从10开始的,从而达到改变仿函数状态的目的。

但庆幸的是如果使用for_each()函数,他会返回仿函数的状态,原理实现容器内元素的遍历,并对每个函数执行回调函数:

#include<iostream>
#include<list>
#include<algorithm>
#include <iterator>
using namespace std;
typedef list<int> List;
class funtion {
private:
	int value;
public:
	funtion(int v = 0):value(v){ }
	void operator()(int elem) {
        value += elem;
	}
    int GET_VALUE() {
        return value;
    }
};
int main()
{
	
	List coll;
    for (int i = 0; i <= 10; i++)
        coll.push_back(i);
    copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    funtion a =  for_each(coll.begin(),coll.end(), funtion());
    cout << endl << a.GET_VALUE() << endl;
    funtion ab = for_each(coll.begin(), coll.end(), funtion(100));
    cout << ab.GET_VALUE() << endl;
	return 0;
}

执行效果
在这里插入图片描述


此外预先定义的仿函数是库中提供的,此处不介绍了,转载一点,截图,来自博客园博主:alex

在这里插入图片描述
在这里插入图片描述

发布了222 篇原创文章 · 获赞 48 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_44116998/article/details/104579393