比较器在C++中的应用

Usage of comparator in C++

本文关键字:应用 C++ 比较器      更新时间:2023-10-16

下面是用于合并k个排序列表的c++代码。但我在阅读前4行代码时感到困惑。我知道它是干什么的,只是弄糊涂了它是怎么做的。有人能给我解释一下这些台词吗?

为什么要使用struct?"operator"后面的"()"是什么意思?既然包括结果列表在内的所有列表都是按升序排列的,为什么要使用">"而不是"<"?

struct compare {
    bool operator() (ListNode* &left, ListNode* &right) {
        return left->val > right->val;
    }
};
class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        priority_queue<ListNode *, vector<ListNode *>, compare> heap;
        for (int i = 0; i < lists.size(); i++) {
            if (lists[i]) heap.push(lists[i]);
        }
        ListNode *dummy = new ListNode(0);
        ListNode *cur = dummy;
        while (!heap.empty()) {
            ListNode *min = heap.top();
            heap.pop();
            cur->next = min;
            cur = min;
            if (min->next) {
                heap.push(min->next);
            }
        }
        return dummy->next;
    }
};

您的struct compare就是函子函数对象

struct compare
{
  bool
  operator() (const ListNode& left, const ListNode& right) const
  {
    return left.val > right.val;
  }
};
void
example_usage(const ListNode& left, const ListNode& right, const compare cmp)
{
  if (cmp(left, right))
    std::cout << "left is greater" << std::endl;
  else
    std::cout << "right is greater" << std::endl;
}

(我已经更改了签名,因为使用了对指针的引用,并使这些非const对我来说太麻烦了。)

在许多情况下,它是使用函数指针的一种方便的替代方法。最重要的是,当在模板中使用时(如您的示例),编译器通常能够内联调用运算符()。使用函数指针并不容易。

目前尚不清楚这在您的示例中是否相关,但通常情况下,函子的优点是它可以在任何地方声明(也可以在函数体内部),而函数只能在全局范围或作为类成员声明。这允许使用函子进行更好的封装。自C++11以来,我们有lambdas作为另一种选择:

auto cmp = [](const ListNode& left, const ListNode& right)->bool{
    return left.val > right.val;
};

它可以像函子一样使用。(在后台,如果你给它一个lambda表达式,编译器很可能会创建一个函子。)

为什么要使用struct?

这里没有必要使用结构,尽管它没有坏处。

"operator"后面的"()"是什么意思?

查找运算符重载教程。

既然包括结果列表在内的所有列表都是按升序排列的,为什么要使用">"而不是"<"?

使用<对于这样的比较,所以我不知道为什么,只是为了尴尬。

此外,参数应该是(const ListNode* left, const ListNode* right),如果在结构内部,则成员函数也应该是const。这里没有必要参考它们。我还会考虑是否需要指针和动态分配的数据结构。

为什么要使用struct

它可以是structclass。它们本质上是相同的东西,而不是1。structs的成员是默认的public并且classes的成员是缺省的private和2。关于人们应该如何将structs用于POD(普通的旧数据)和将classes用于其他一切的一般意见。

"operator"后面的"()"代表什么

这个很有趣。... operator()(...)定义函数调用运算符的重载。无论何时调用函数,都肯定会使用此运算符,将参数封装在括号中,并使返回值成为表达式的结果。

附带说明一下,具有过载函数调用运算符的classstruct通常被称为functor

既然包括结果列表在内的所有列表都是按升序排列的,为什么要使用">"而不是"<"

这也是另一个有趣的问题。其思想是,STL(标准模板库)旨在供几乎所有使用C++的人使用,并旨在为执行某些操作提供便利。因此,STL中的所有工具都可以用于任何类型,包括用户定义的类型。

但是,用户定义的类型默认情况下没有重载<>等运算符,因此用户将不得不重载它们。

CCD_ 19的结果与CCD_ 20的结果基本相同。现在想象一下,如果其中一些工具使用<,而另一些则使用>。每个人都必须重载两个运算符,即使它们只是彼此的补充,并且可以用来替换彼此。

因此,设置了一个标准,使得STL将只使用>运算符,并且只要求您重载一个运算符。

顺便说一句,您可以使用std::less模板化函子进行简单的操作,如小于比较,而不是编写自己的比较函子,并使用std::函数进行更复杂的操作。

感谢您的阅读。