为啥 STL 优先级队列错误地对我的类对象进行排序

Posted

技术标签:

【中文标题】为啥 STL 优先级队列错误地对我的类对象进行排序【英文标题】:Why is STL priority queue incorrectly sorrting my class objects为什么 STL 优先级队列错误地对我的类对象进行排序 【发布时间】:2019-10-25 08:52:40 【问题描述】:

我重载了< 运算符,如图所示,但每次运行程序时,我的类对象似乎都是随机排序的。

class Node

int decimal_value
public:
    Node(int decimal) : decimal_value(decimal)
    
    friend bool operator<(const Node& p1, const Node& p2);
;

 bool operator<(const Node& p1, const Node& p2)

    return p1.decimal_value < p2.decimal_value;


int main()

    Node* n1= new Node(5);
    Node* n2 = new Node(4);

    priority_queue<Node*> my_q;
    my_q.push(n1);
    my_q.push(n2);

这可能是因为我使用了指向节点的指针而不是节点本身吗?如果是这样,我该如何解决?

【问题讨论】:

在创建minimal reproducible example 向我们展示时,请确保它复制了您遇到的问题,并且不包含任何其他不相关的错误。 您的运算符重载与指针的优先级队列无关。他们正在使用股票指针价值比较的面值进行比较。将自定义比较器类型作为队列的附加参数。 是的,问题很可能是因为您有一个指针队列,因此将调用的比较运算符是bool operator&lt;(Node*, Node*) 查看link priority_queue&lt;Node&gt; 有什么问题?如果你真的必须存储指针,你应该存储智能指针(除非其他人负责释放它们) 【参考方案1】:

priority_queue&lt;Node*&gt; my_q; 将比较 Node* 类型的元素进行排序,它不会为您取消引用这些指针并调用您的重载运算符。并且不相关指针的比较具有un定义的行为,但在您的情况下不会产生有用的结果。

当你修复了这个,会有另一个bug:你从来没有初始化decimal_value,所以它的值是未定义/随机的。

一种解决方案是明确指定一个比较器:

struct MyComparator 
    bool operator()(const Node*l, const Node*r) const 
        return l->decimal_value < r->decimal_value;
    
;

std::priority_queue<Node*, std::vector<Node*>, MyComparator> q;

【讨论】:

不相关指针的比较有defined behavior(虽然只是部分排序)。减法does not. 我明白了,那么有没有办法使用 priority_queue 对指针指向的内容进行排序? @Risen,我加了一个小例子:) @MaxLanghof 嗯,我记得不相关的指针之间的指针比较也是 UB。 C ++ 11可能会改变吗?不幸的是,目前无法使用旧标准... @Aconcagua 在 C++11 中,它是明确定义的(尽管大多未指定):timsong-cpp.github.io/cppwp/n3337/expr.rel#2。 n1905 from 2005 类似。让我看看哪里有更旧的草稿...

以上是关于为啥 STL 优先级队列错误地对我的类对象进行排序的主要内容,如果未能解决你的问题,请参考以下文章

stl-优先队列

STL - priority_queue(优先队列)

为啥我需要在 C++ 中使用不同的排序格式来对这个 USACO 代码上的数组和优先级队列进行排序?

学习:STL----优先队列

优先队列 stl 拓扑排序

用户定义类型的优先级队列