C ++ priority_queue pop()和top()差异

时间:2017-03-08 17:14:44

标签: c++

我很难理解为什么priority_queue pop()调用没有删除top()元素。优先级队列具有自定义比较结构,因此较低的数字具有较高的优先级(因此应使用top()检索。

调试文本(如下所示)显示top()元素即使在pop()之后也保持不变。

即使我们假设比较结构有点错误,top()应该在pop()之后改变,对吧?我还能看到什么来理解为什么会这样。 priority_queue代码本身对我来说有点难以理解......

请注意,此行为不一致。还有一些时候top()在pop()之后发生了变化。

有什么想法吗?谢谢!

调试文本(使用top()前面显示的top()进行编辑:

size BEFORE push(): 1 TOP: [1488994840.745965281:0106996627] APPENDING: [1488994840.746157190:0106996627]
size  AFTER push(): 2 TOP: [1488994840.745965281:0106996627]
size BEFORE  pop(): 2 TOP: [1488994840.745965281:0106996627]
size  AFTER  pop(): 1 TOP: [1488994840.745965281:0106996627] // <- same top()!!

我将()推送到priority_queue:

void Replica::appendPrepareOK(const PrepareOK &prepareOK) {
    PendingPrepare tmpPrepareOK = prepareOK;

    lock_guard<mutex> lck (this->lockPendingPrepare);

    this->logprint(3, "size BEFORE push(): " + to_string(this->pendingPrepare.size()) + " APPENDING: " + to_string(tmpPrepareOK));

    this->pendingPrepare.push(tmpPrepareOK);

    this->logprint(3, "size  AFTER push(): " + to_string(this->pendingPrepare.size()) + " TOP: " + to_string(this->pendingPrepare.top()));
}

我从priority_queue中弹出():

void Replica::sendPendingCmds() {
    ClockCommand *prepareCmd = NULL;
    PrepareOK *prepareOKCmd = NULL;
    Broadcast *broadcastCmd = NULL;

    {
        lock_guard<mutex> lck(this->lockPendingPrepare);

        if (! this->pendingPrepare.empty()) {
            this->logprint(3, "size BEFORE pop(): " + to_string(this->pendingPrepare.size()) + " TOP: " + to_string(this->pendingPrepare.top()));

            PendingPrepare firstCommand = this->pendingPrepare.top();
            this->pendingPrepare.pop();

            if (! this->pendingPrepare.empty()) {
                this->logprint(3, "size  AFTER pop(): " + to_string(this->pendingPrepare.size()) + " TOP: " + to_string(this->pendingPrepare.top()));
            }
            else {
                this->logprint(3, "size  AFTER pop(): " + to_string(this->pendingPrepare.size()));
            }

priority_queue的定义:

typedef priority_queue<PendingPrepare, deque<PendingPrepare>, PendCompare> pendQueue;

自定义PendCompare比较类:

class PendCompare {
public:
    bool operator() (const PendingPrepare &a, const PendingPrepare &b) const {
        if (a.prepareOK != NULL) {
            if (b.prepareOK != NULL) { return a.prepareOK->tsOK > b.prepareOK->tsOK; }
            else if (b.prepare != NULL) { return a.prepareOK->tsOK > b.prepare->ts; }
        }
        else if (a.prepare != NULL) {
            if (b.prepareOK != NULL) { return a.prepare->ts > b.prepareOK->tsOK; }
            else if (b.prepare != NULL) { return a.prepare->ts > b.prepare->ts; }
        }

        return false;
    }
};

PendingPrepare结构的相关部分:

struct PendingPrepare {
    ClockCommand* prepare = NULL;
    PrepareOK* prepareOK = NULL;

    void operator=(const PrepareOK &b) {
        this->prepareOK = new PrepareOK(b);
    }
};

1 个答案:

答案 0 :(得分:0)

感谢大家的帮助。实际上查看PendingPrepare内容解决了这个问题。我做了一个可怕的假设,即只有一个指针一次被实例化,当有两个实例化时,会混淆PendCompare比较类。

更好的复制构造函数删除并使其他指针为NULL以避免多个实例化解决了问题。