【问题标题】:C++ Priority Queue with customized object具有自定义对象的 C++ 优先级队列
【发布时间】:2018-04-29 22:54:41
【问题描述】:

我试图了解比较器如何用于优先级队列,我做了几个测试:

测试1:创建比较器类,并使用priority_queue<T, vector<T>, cmp>

它总是很好用

测试 2:

struct test {
    int a = 0;
};

bool operator<(const test& lhs, const test& rhs) {
    return lhs.a < rhs.a;
}

int main() 
{
    priority_queue<test> pq;
}

这按预期工作。

测试 3:将测试 2 放在一个类中

class T{
    struct test {
        int a = 0;
    };

    bool operator<(const test& lhs, const test& rhs) {
        return lhs.a < rhs.a;
    }
};

编译错误:

'bool T::operator<(const T::test&, const T::test&)' must take exactly one argument

似乎编译器认为我为类T重载了运算符

测试 4:重载运算符

struct test {
    int a = 0;
    bool operator<(const test& rhs) {
        return a < rhs.a;
    }
};

int main() 
{
    vector<test> v;
    sort(v.begin(), v.end());   // No error
    set<test> s;                // No error
    priority_queue<test> pq;    // Compiling error
}

只有priority_queue会报错:

'passing 'const test*' as 'this' argument discards qualifiers'

我不知道为什么这适用于排序和设置,但不适用于优先级队列。

【问题讨论】:

  • 您将operator&lt; 设为T 的方法。要么在 T::test 内声明为好友,要么完全在 T 外声明。
  • 4: stackoverflow.com/questions/550428/… ,比较不应该改变被比较的对象。
  • 第二个问题的答案是,如果运算符不会更改 lhs(它不是​​),则它应该是 const 限定的。在{ 之前粘贴const。请每个问题问一个问题。

标签: c++ comparator priority-queue


【解决方案1】:

operator&lt; 必须接受两个参数,而当您使其成为class T 的成员时,它会隐式获取this 作为第三个参数,因此测试 3 中的错误:

class T {
  bool operator<(const test& lhs, const test& rhs) { // error
    return lhs.a < rhs.a;
  }
};

要解决此问题,请在嵌套的 test 类中定义 operator&lt;

class T {
public:
  struct test {
    int a = 0;
    friend bool operator<(const test& lhs, const test& rhs) {
      return lhs.a < rhs.a;
    }
  };
};

或在命名空间范围内。

在测试 4 中,operator&lt; 应该是 const

struct test {
  int a = 0;
  bool operator<(const test& rhs) const {
    return a < rhs.a;
  }
};

【讨论】:

  • 非常感谢!我对测试 4 仍然有些困惑。为什么 sort 和 set 不需要 const 签名?对我来说,它看起来不太一致。
  • @Seraph 我认为从技术上讲priority_queue 不一定需要const,但是以这种方式定义的operator&lt; 会不一致并且test 不会满足LessThanComparable 的概念:en.cppreference.com/w/cpp/concept/LessThanComparable
【解决方案2】:

priority_queue 的比较器与任何其他比较器一样工作。应该可以参与表达

if (compare(element1, element2))

默认实现减少到

if (element1 < element 2) ....

你在 3 中所做的导致

if ( tObject.operator<(anotherTObject, yetAnotherTObject))

所以你的

bool T::operator<(const test& lhs, const test& rhs) {
    return lhs.a < rhs.a;
}

真的应该和对象本身比较

bool T::operator<(const test& rhs) const {
    auto lhs = *this;
    return lhs.a < rhs.a;
}

最后一个 const 的作用类似于 vitauts 合理答案中第一个参数的 const。

【讨论】:

  • 非常感谢!我对测试 4 仍然有些困惑。为什么 sort 和 set 不需要 const 签名?对我来说,它看起来不太一致。
  • @Seraph 在优先级队列中,您不能更改结构内的键,否则队列将无效。对于一个集合也是如此。
  • 再次感谢。我做了一些进一步的测试,声明集合时没有错误,但是如果我尝试插入一个对象,它会抛出同样的错误。
  • @Seraph 测试良好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
相关资源
最近更新 更多