[STL]sort和priority_queue中使用仿函数时的不同

一、问题提出

1.自定义比较函数的sort

我们可以使用自定义的cmp函数、lambda函数或者less< int >()、greater< int >()作为自定义compare对象作为参数传给sort函数,达到自定义比较顺序的结果。代码如下:

  1. 使用自定义cmp函数
bool cmp(const int &a, const int &b){
	return a
  1. 使用lambda函数
sort(vec.begin(), vec.end(), [](int a, int b){return a
  1. 使用less< int >()或者greater< int >()
sort(vec.begin(), vec.end(), less());
2.自定义排序函数的priority_queue

对于priority_queue(优先队列)可以使用仿函数(函数对象类)自定义compare顺序,代码如下:

class Cmp{
public:
	bool operator()(int a, int b){
		return a, Cmp> pri_que;
3.问题提出

而自定义sort时并不能使用仿函数名Cmp,例如如下代码是错的:

// 这个代码是错的
class Cmp{
public:
	bool operator()(int a, int b){
		return a

这是为什么呢?

3.什么是仿函数、函数对象类和函数对象

我在查资料时发现网上对仿函数的定义有冲突。

Functors are objects that can be treated as though they are a function
or function pointer.
仿函数(functor)是一个可以被视作函数或者函数指针的对象1

这段说仿函数是一个对象,可以看做是一个函数或者函数指针。

A functor (or function object) is a C++ class that acts like a function. Functors are called using the same old function call syntax. To create a functor, we create a object that overloads the operator().
仿函数(又叫函数对象)是一个可以像函数一样运行的C++类。调用仿函数与调用函数的语法相同。为了产生一个仿函数,我们需要重载类的"()"运算法1

这段又说仿函数是一个重载了"()"运算符的类。到底是类还是对象这里也没有说清楚。
而中文搜索的结果大多是:

仿函数又称为函数对象,是一种能够行使函数功能的类。

我个人倾向于认为仿函数是一个类,也叫函数对象类。而将仿函数实例化得到的对象(函数对象)可以看作一个函数或函数指针。下面给出代码举例:
代码举例:

// 这是一个类,仿函数(函数对象类),重载了"()"运算符
class Cmp{
public:
	bool operator()(int a, int b){
		return a

二、原因

1.sort源代码

从sort函数的定义如下2:

template< class RandomIt, class Compare >
constexpr void sort( RandomIt first, RandomIt last, Compare comp );

可以看到sort是一个模板函数,这里需要三个输入参数(完整的sort函数并不必须要有三个输入参数,详情见2)。
第一、二个参数是需要排序的迭代器,第三个参数comp是一个Compare类的对象

2.priority_queue源代码

priority_queue的定义如下3:

template<
    class T,
    class Container = std::vector,
    class Compare = std::less
> class priority_queue;

priori_queue是一个模板类,类型参数表为T、Container和Compare,这三者都是类(Class)。我们关注的Compare类默认为std::less< typename Container::value_type>。

3.总结

从上面我们可以知道。对于模板函数sort,我们需要在sort的参数列表"()"中给出自定义的Compare类的对象实例,而对于模板类priority_queue,我们需要在其类型参数表 "<>"中给出自定义的Compare类
因此使用仿函数作为cmp的合法代码如下:

class Cmp{
public:
	bool operator() (int a, int b){
		return a, Cmp> pri_que;	//

这就是sort和priority_queue在使用仿函数做自定义比较参数时的不同。
至于为什么一个需要 使用实例化后的对象,一个需要使用类名。相信读者也可以看出,因为本质上sort是一个函数,函数参数列表中需要传入实例化后的具体对象,而priority_queue是一个模板类,模板的类型参数表中<>需要传入具体的类,而不是对象。

四、其他

还有一个问题是,priority_queue的类型参数列表中需要传入类名,而lambda函数是一个匿名的类型,所以不能直接使用lambda函数声明priority_queue,需要做些改变,具体的用法可以参考这篇博客,本文中部分内容也参考了该文章。


  1. www.geeksforgeeks.org/functors-in-cpp ↩︎ ↩︎

  2. https://en.cppreference.com/w/cpp/algorithm/sort ↩︎ ↩︎

  3. https://en.cppreference.com/w/cpp/container/priority_queue ↩︎

你可能感兴趣的:(STL,C++,stl,c++,sort,priority_queue)