C++ priority_queue pop() and top() discrepancy



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

调试文本(下图)显示top()元素即使在pop()之后保持相同。

即使我们假设比较结构以某种方式是错误的,top()应该在pop()之后更改,对吗?我还能看什么来理解为什么会发生这种情况。目前,Priority_queue代码本身对我来说有点难以理解...

请注意,此行为不一致。在其他时候,pop()后top()更改。

有什么想法吗?谢谢!

调试文本(在push()之前显示为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中pop():

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;
    }
};

悬浮式构造的相关部分:

struct PendingPrepare {
    ClockCommand* prepare = NULL;
    PrepareOK* prepareOK = NULL;
    void operator=(const PrepareOK &b) {
        this->prepareOK = new PrepareOK(b);
    }
};

感谢大家的帮助。实际上,查看悬挂的内容解决了问题。我做出了一个可怕的假设,即一次有时会实例化,只有一个指示可以实例化,这两者都被实例化,从而使PendCompare比较类别感到困惑。

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

最新更新