所谓的仿函数,就是定义一个operator()
的对象。
仿函数的三个优点:
- 仿函数可以拥有成员函数和成员变量。通常如在类中实现的,可以增加其他成员。
- 每一个仿函数都有自己的型别。可以进行模板化实现,即实现多个状态。
- 仿函数通常快于一般函数,因为通常在编译阶段就完成了许多细节。
示例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