【C++】STL函数对象

三、函数对象(类似C的函数指针)

函数对象 =》 C语言里面的函数指针

使用C的函数指针实现比大小效率低的问题

template<typename T>
bool mygreater(T a, T b)
{
	return a > b;
}

template<typename T>
bool myless(T a, T b)
{
	return a < b;
}

template<typename T, typename Compare>
bool compare(T a, T b, Compare comp)  //Compare推导出来是函数指针
{
    //通过函数指针调用函数,是没有办法内联的,所以会有函数调用开销,效率很低
	return comp(a, b);
}

int main()
{
	cout << compare(1, 2, mygreater<int>) << endl;  //0
	cout << compare(1, 2, myless<int>) << endl;     //1
}

通过函数指针调用函数,为什么没有办法内联?

答:编译阶段comp函数指针并不知道它具体要调用mygreater还是myless,所以没有办法内联,只有运行的时候才会跑到这个函数指针具体指向的地址上执行指令

通过函数指针调用函数,是没有办法内联的,所以会有函数调用开销,效率很低。

C++使用函数对象比大小

template<typename T>
class mygreater
{
public:
    bool operator()(T a, T b)  //两个参数:二元函数对象
    {
        return a>b;
    }
};
template<typename T>
class myless
{
public:
    bool operator()(T a, T b)
    {
        return a<b;
    }
};
template<typename T, typename Compare>
bool compare(T a, T b, Compare comp)  //Compare推导出来是函数对象
{
	return comp(a, b);  //operator()(a,b);
}

int main()
{
    //现在传入的是mygreater与myless的无名对象,Compare推导出来的就是具体对象的operator()(a,b),即编译过程中comp知道具体调用的是哪个对象的哪个函数,所以可以内联,省下函数调用开销,调高效率
	cout << compare(1, 2, mygreater<int>()) << endl;  //0
	cout << compare(1, 2, myless<int>()) << endl;     //1
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-upseSD2V-1650361949968)(img/1C++%EF%BC%9ASTL%E3%80%81%E5%AE%B9%E5%99%A8.img/image-20210227225554868.png)]
使用函数对象的好处:

  • 通过函数对象调用operator(),可以通过内联省略函数的调用开销,比通过函数指针调用函数(不能内联)效率高。(使用函数对象虽然我们没有显示加上inline关键字,但编译器优化时可能会优化成内联)
  • 因为函数对象是用类生成的,所以类中可以添加相关的成员变量,用来记录函数对象使用时的更多信息

函数对象使用示例1:将优先级队列从大根堆修改为小根堆

priority_queque原型:第三个参数默认是less,修改为greater就可以实现小根堆了

#include <queue>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
	//输出优先级队列,默认从大到小,底层vector,大根堆
	priority_queue<int> que1;
	for (int i = 0; i < 10; ++i)
	{
		que1.push(rand() % 100);
	}
	cout << "默认输出顺序:(大根堆)" << endl;
	while (!que1.empty())
	{
		cout << que1.top() << " ";
		que1.pop();
	}
	cout << endl << endl;

	//通过修改优先级队列的函数对象,使得其组织方式从大根堆变成小根堆,从小到大输出
	using MinHeap = priority_queue<int, vector<int>, greater<int>>;//默认第三个参数是less,修改为greater就变成小根堆了
	MinHeap que2;  //底层vector,大根堆
	for (int i = 0; i < 10; ++i)
	{
		que2.push(rand() % 100);
	}
	cout << "修改为小根堆之后的输出结果:" << endl;
	while (!que2.empty())
	{
		cout << que2.top() << " ";
		que2.pop();
	}
	cout << endl << endl;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bqFuBKMI-1650361949969)(img/C++%EF%BC%9ASTL%E3%80%81%E5%AE%B9%E5%99%A8.img/image-20210225112541229.png)]

函数对象使用示例2:将set从小到大输出改变为从大到小输出,set底层是红黑树

set原型:第二个参数是函数对象,默认是less,修改为greater就可以从大到小输出了

#include <iostream>
#include <set>
using namespace std;

int main()
{
	set<int> set1;
	for (int i = 0; i < 10; ++i)
	{
		set1.insert(rand() % 100);
	}
	cout << "set默认输出:" << endl;
	for (int v : set1)
	{
		cout << v << " ";
	}
	cout << endl << endl;

	set<int, greater<int>> set2;
	for (int i = 0; i < 10; ++i)
	{
		set2.insert(rand() % 100);
	}
	cout << "set将less改成greater后的输出:" << endl;
	for (int v : set2)
	{
		cout << v<<" ";
	}
	cout << endl << endl;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cq12JYV5-1650361949970)(img/C++%EF%BC%9ASTL%E3%80%81%E5%AE%B9%E5%99%A8.img/image-20210225114109700.png)]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值