c ++ - 优先级队列 - 它在内部如何工作?

时间:2013-12-30 22:30:58

标签: c++ operator-overloading priority-queue

假设我有一个优先级队列的声明:

    struct orderByRewards{

    bool operator() (pair<int,pair<int,int> > a, pair<int, pair<int, int> > b){
        return a.first < b.first;
    }
};

priority_queue<pair<int,pair<int,int> >, vector<pair<int,pair<int,int> > >, orderByRewards> Q;

我想知道是否有人可以花时间解释我编译器如何解释比较类。

  • 为什么我需要重载()运算符?
  • 另外,比较过程中使用的()运算符在哪里?

感觉有点奇怪,特别是因为我对模板和所有OOP概念都不太满意。

为什么我们需要声明单个对象的类型和容器类型?

3 个答案:

答案 0 :(得分:1)

您不需要重载运算符()。您可以声明自定义方法:

typedef bool (*comp)(int,int);
bool compare(int a, int b)
{
   return (a<b);
}
int main()
{
    std::priority_queue<int,std::vector<int>, comp> pq(compare);
    return 0;
}

<强>更新: 正如@WhozCraig指出: 可以在不重载operator()的情况下使用此对象,但编译器将面临更简单的内联operator()比较函数,而不是运行时提供的解除引用的比较函数

答案 1 :(得分:1)

你实际上是在询问函数对象(或函子)。函数对象是重载operator()的对象。您可以使用这样的对象,就像它是一个函数一样。该标准提供了一些比较函子(如orderByRewards)。例如,std::less看起来像这样:

template <class T>
struct less {
  constexpr bool operator()(const T &lhs, const T &rhs) const 
  {
    return lhs < rhs;
  }
};

正如我们所看到的,重载的operator()只是使用<比较两个参数,然后返回布尔结果。要使用它,您需要创建一个std::less类型的对象,然后在其上使用函数调用语法:

std::less<int> compare;
assert(compare(5, 7) == true);

即使compare是一个对象,我们也可以像compare(5, 7)中的函数一样使用它。

现在我们知道你的类型orderByRewards是一个函数对象类型。您将其作为std::priority_queue的模板类型参数传递。然后std::priority_queue的实现可以在需要比较队列中的元素时创建此比较函数对象的对象。

考虑一个更简单的例子:

template <typename T, typename Comp>
struct foo {
  void bar(T a, T b) {
    Comp compare;
    if (compare(a, b)) {
      std::cout << "True" << std::endl;
    } else {
      std::cout << "False" << std::endl;
    }
  }
};

这是一个愚蠢的例子,但它得到了重点。我们可以像这样使用它:

foo<int, std::less<int>> my_foo;
my_foo.bar(5, 7); // Will print true

我们能够通过传递一些任意比较函数类型来配置foo,它的成员函数bar能够实例化并使用它。

因此,以同样的方式,您通过为其提供比较函数类型来配置std::priority_queue,它可用于对队列中的元素进行排序。这是它如何确定元素之间的优先级。实际上,std::priority_queue的默认模板类型参数是std::less

答案 2 :(得分:1)

考虑std::priority_queue的定义并从那里开始工作也许最有意义。

template <class T, class Container = vector<T>, 
          class Compare = less<typename Container::value_type> >
class priority_queue {

这表示Compare是某种类型,默认为std::less<T>,T =底层容器的value_type。这可以补偿你可能会做一些有点疯狂的事情,比如创建一种类型的priority_queue,但让底层容器保持另一种类型(虽然这不是特别可能,除非意外)。

反过来,

std::less的定义如下:

template <class T> struct less {
    bool operator()(const T& x, const T& y) const;
    // plus a few typedefs for the argument and return types.
};

简而言之,它是一个只有一个公开可用操作定义的类型:operator()可以传递两个它比较的项目,并返回bool以指示第一个是否小于第二

由于这是std::priority_queue期望使用的内容,因此无论您提供什么,都必须支持基本相同的函数调用语法和语义(例如,operator()应该采用const个参数并且应该自己是const限定的。)