c++ STL (四 仿函数)
1. 概念
模仿函数的类,使用方式如同函数。本质是类中重载括弧运算符operator()
。
2. 场景
不同函数复用相同处理代码。
3. 使用
3.1 C语言的处理方式
使用函数指针和回调函数来实现代码复用。例如qsort()
#include <stdio.h>
#include <stdlib.h>
int arr_sort( const void *a, const void *b) {
return *(int*)a-*(int*)b;
}
int main() {
int arr[5] = { 4, 1, 2, 5, 6 };
qsort(arr, 5, sizeof(arr[0]), arr_sort);
int i;
for (i = 0; i < 5; i++){
printf("%i\n", arr[i]);
}
return 0;
}
3.2 C++语言的处理方式
- 函数指针方式
#include <iostream>
#include <algorithm>
using namespace std;
inline bool Sort(int a,int b){
return a > b;
}
inline void Display(int a){
cout << a << endl;
}
int main() {
int arr[5] = { 4, 1, 2, 5, 6 };
sort(arr, arr+5,Sort);
for_each(arr,arr+5,Display);
return 0;
}
- 函数模板方式
#include <iostream>
#include <algorithm>
using namespace std;
template<class T>
inline bool Sort(T const& a,T const& b){
return a > b;
}
template<class T>
inline void Display(T a){
cout << a << endl;
}
int main() {
int arr[5] = { 4, 1, 2, 5, 6 };
sort(arr, arr+5,Sort<int>);
for_each(arr,arr+5,Display<int>);
return 0;
}
- 仿函数方式
class Sort{
public:
bool operator()(int a,int b) const {
return a > b;
}
};
class Display{
public:
void operator()(int a) const{
cout << a << endl;
}
};
int main()
{
int arr[5] = { 4, 1, 2, 5, 6 };
sort(arr, arr+5,Sort());
for_each(arr,arr+5,Display());
return 0;
}
4.仿函数模板方式
template<class T>
class Sort{
public:
inline bool operator()(T const& a,T const& b) const {
return a > b;
}
};
template<class T>
class Display{
public:
inline void operator()(T const& a) const{
cout << a << endl;
}
};
int main()
{
int arr[5] = { 4, 1, 2, 5, 6 };
sort(arr, arr+5,Sort<int>());
for_each(arr,arr+5,Display<int>());
return 0;
}
STL的仿函数
在<functional>
头文件中定义了如下三类仿函数:
- 算术类仿函数
操作 | 仿函数 |
---|---|
加 | plus<T> |
减 | minus<T> |
乘 | multiplies<T> |
除 | divides<T> |
取模 | modulus<T> |
取反 | negate<T> |
template< class T>
struct plus:binary_function<T,T,T>{
public:
T operator()(T const& l,T const&r){
return l+r;
}
};
例如:
#include <iostream>
#include <numeric> // accumulate
#include <functional> //
using namespace std;
int main(){
int arr[]={1,2,3,4,5};
vector<int> iv(ia,ia+5);
cout<< accumulate(iv.begin(),iv.end(),1,multiplies<int>()) <<endl;
return 0;
}
Boost lambda表达式
cout<< accumulate(iv.begin(),iv.end(),1,_1*_2) <<endl;
或者
#include <iostream>
#include <algorithm> // for_each() transform()
#include <functional>
using namespace std;
inline void Print(int a){
cout << a << endl;
}
int main(){
int first[]={1,2,3,4,5};
int second[]={10,20,30,40,50};
int results[5];
transform (first, first+5, second, results, std::plus<int>());
for_each(results,results+5,Print);
return 0;
}
Boost lambda表达式
transform (first, first+5, second, results, _1+_2);
- 关系运算类仿函数
操作 | 仿函数 |
---|---|
等于 | equal_to<T> |
不等于 | not_equal_to<T> |
大于 | greater<T> |
大于等于 | greater_equal<T> |
小于 | less<T> |
小于等于 | less_equal<T> |
template< class T>
struct equal_to:binary_function<T,T,bool>{
public:
bool operator()(T const& l,T const&r){
return l == r;
}
};
例如:
#include <iostream>
#include <algorithm> // for_each() sort()
#include <functional>
using namespace std;
inline void Print(int a){
cout << a << endl;
}
int main(){
int arr[]={1,2,3,4,5};
sort(arr,arr+5,greater<int>());
for_each(arr,arr+5,Print);
return 0;
}
Boost lambda表达式
sort(arr,arr+5,_1>_2);
- 逻辑运算仿函数
操作 | 仿函数 |
---|---|
逻辑与 | logical_and<T> |
逻辑或 | logical_or<T> |
逻辑否 | logical_not<T> |
例如:
布尔数组整体取反
#include <iostream> // cout, boolalpha
#include <functional> // std::logical_not
#include <algorithm> // std::transform
using namespace std;
inline void Print(bool a){
cout << a << endl;
}
int main () {
bool values[] = {true,false,true,false};
transform (values, values+4, values, logical_not<bool>());
cout.flags(ios::boolalpha);
for_each(values, values+4,Print);
return 0;
}
Boost lambda表达式
transform (values, values+4, values, !_1);
两个布尔数组对应元素相与
#include <iostream> // cout, boolalpha
#include <functional> // std::logical_not
#include <algorithm> // std::transform
using namespace std;
inline void Print(bool a){
cout << a << endl;
}
int main () {
bool values1[] = {true,false,true,false};
bool values2[] = {false,true,false,true};
bool result[4];
transform(values1, values1+4,values2, result, logical_and<bool>());
cout.flags(ios::boolalpha);
for_each(result,result+4,Print);
return 0;
}
Boost lambda表达式
transform(values1, values1+4,values2, result, _1 and _2);