> 文章列表 > 【C++初阶】比较仿函数/函数对象入门

【C++初阶】比较仿函数/函数对象入门

【C++初阶】比较仿函数/函数对象入门

🌟hello,各位读者大大们你们好呀🌟

🍭🍭系列专栏:【C++学习与应用】

✒️✒️本篇内容:比较仿函数代码样例,比较仿函数三种不同难度的应用示例

🚢🚢作者简介:计算机海洋的新进船长一枚,请多多指教( •̀֊•́ ) ̖́-

目录

一、代码样例 

二、使用场景(示例)

1.简单应用

2.冒泡排序

3.priority_queue的模拟实现


一、代码样例 

比较仿函数相当于一个类对象,通常使用它的时候要求重载一个运算符 —— 括号运算符【operator()】

因为是比较仿函数,返回默认值,所以我们通常使用bool

bool operator()() 

 为了让仿函数使用更广泛,可将其变为模板

下面代码就实现了 x 和 y 的比较

	template<class T>class less{//class默认私有,所以需要加publicpublic:bool operator()(const T& x, const T& y) const{return x < y;}};
	template<class T>class greater{public:bool operator()(const T& x, const T& y) const{return x > y;}};

为了与库区别开来,我们通常会创造一个命名空间存放比较仿函数

#include<iostream>
using namespace std;// 仿函数/函数对象
namespace Lin
{template<class T>class less{public:bool operator()(const T& x, const T& y) const{return x < y;}};template<class T>class greater{public:bool operator()(const T& x, const T& y) const{return x > y;}};
}

二、使用场景(示例)

1.简单应用

仿函数的对象可以像函数一样使用,因此被称为仿函数

int main()
{Lin::less<int> lessFunc;lessFunc(1, 2);    //等价于下方的运算符重载//lessFunc.operator()(1, 2);
}

2.冒泡排序

添加一个额外的模板Compare,在函数中创建一个Compare的对象com,使代码运行时能进行推演。

转化前

template<class T>
void BubbleSort(T* a, int n)
{...if (a[i] < a[i - 1])...
}

转化后 

template<class T, class Compare>
//void BubbleSort(T* a, int n, const Compare& com) - 没有成员变量的类只有1个字节,拷贝代价不大,因此可以不用&
void BubbleSort(T* a, int n, Compare com)
{for (int j = 0; j < n; ++j){int exchange = 0;for (int i = 1; i < n - j; ++i){//if (a[i] < a[i - 1])if (com(a[i], a[i - 1])){swap(a[i - 1], a[i]);exchange = 1;}}if (exchange == 0){break;}}
}

测试用例

int main()
{Lin::less<int> lessFunc;Lin::greater<int> greaterFunc;int a[] = { 2, 3, 4, 5, 6, 1, 2, 4, 9 };//升序//BubbleSort(a, sizeof(a) / sizeof(int), lessFunc); - lessFunc有名对象BubbleSort(a, sizeof(a) / sizeof(int), Lin::less<int>()); //Lin::less<int>()匿名对象for (auto e : a){cout << e << " ";}cout << endl;//降序BubbleSort(a, sizeof(a) / sizeof(int), greaterFunc);for (auto e : a){cout << e << " ";}cout << endl;return 0;
}

3.priority_queue的模拟实现

#include<iostream>
#include<vector>
using namespace std;namespace Lin
{template<class T>class less{public:bool operator()(const T& x, const T& y) const{return x < y;}};template<class T>class greater{public:bool operator()(const T& x, const T& y) const{return x > y;}};template<class T, class Container = vector<T>, class Compare = less<T>>class priority_queue{public:priority_queue(){}template <class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first, last){// for (int i = (_con.size() - 1 - 1) / 2; i >= 0; --i){adjust_down(i);}}void adjust_up(size_t child){Compare com;size_t parent = (child - 1) / 2;while (child > 0){//if (_con[parent] < con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);}void adjust_down(size_t parent){Compare com;size_t child = parent * 2 + 1;while (child < _con.size()){//if (child+1 < _con.size() && _con[child] < _con[child+1])if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){child++;}//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}const T& top() const{return _con[0];}bool empty() const{return _con.empty();}size_t size() const{return _con.size();}private:Container _con;};
}int main()
{//Lin::priority_queue<int> pq; // < // 大堆 - 缺省Lin::priority_queue<int, vector<int>, greater<int>> pq; // >  // 小堆pq.push(3);pq.push(1);pq.push(2);pq.push(5);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;return 0;
}


事实上,仿函数的不仅仅只有比较仿函数一种,比较仿函数的应用场景也不仅有博主所列出来的那么少,如果大家有兴趣的话,不妨去找更多相关资料继续深入学习,这里博主仅作入门级讲解,希望能抛砖引玉。

🌹🌹 比较仿函数的知识大概就讲到这里啦,博主后续会继续更新更多C++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪