【问题标题】:Access violation in custom comparator in priority queue优先级队列中的自定义比较器中的访问冲突
【发布时间】:2021-09-25 10:50:53
【问题描述】:

我的一个问题是我的程序引发了访问冲突。 通过调试我发现由于某种原因比较器功能为空。 但是我不确定为什么会这样或如何解决它。

我创建了一个最小的工作示例来重现该问题:

#include "Tryout.h"
#include <queue>

struct Event {
    uint64_t mv_timeout;
};

bool CompareEvents(const Event& a, const Event& b) {
    return a.mv_timeout < b.mv_timeout;
}

int main() {
    std::priority_queue<Event, std::vector<Event>, decltype(&CompareEvents)> mt_eventQueue;
    Event lo_event1{
        .mv_timeout = 1,
    };
    Event lo_event2{
        .mv_timeout = 2,
    };
    mt_eventQueue.push(lo_event1);
    mt_eventQueue.push(lo_event2);
    return 0;
}

在添加第二个事件时执行它会崩溃。

在 Tryout.exe 中的 0x0000000000000000 处引发异常:0xC0000005: 访问冲突执行位置 0x0000000000000000。

如前所述,比较函数似乎为空,即使我通过模板传递它也很难。
这里出了什么问题?

【问题讨论】:

    标签: c++ priority-queue


    【解决方案1】:

    需要在构造函数中明确指定比较函数

    std::priority_queue<Event, std::vector<Event>, decltype(&CompareEvents)> mt_eventQueue( CompareEvents );
    

    否则默认参数将用于产生空指针的比较函数。

    使用的构造函数具有以下带有默认参数的声明

    explicit priority_queue(const Compare& x = Compare(), Container&& = Container());
    

    【讨论】:

    • 这是一个简单的解决方案 - 谢谢!
    • @user2089648 完全没有。不客气。:)
    【解决方案2】:

    比较器函数的模板参数仅提供函数的类型,您仍然需要提供与该类型匹配的实际函数到std::priority_queue 的实例(通过其constructor)。

    如果您自己定义小于运算符,则无需为std::priority_queue 显式提供任何其他模板参数。

    例如:

    struct Event
    {
        uint64_t mv_timeout;
    };
    
    bool operator<(const Event &a, const Event &b)
    {
        return a.mv_timeout < b.mv_timeout;
    }
    
    int main()
    {
        std::priority_queue<Event> mt_eventQueue;
        Event lo_event1{
            .mv_timeout = 1,
        };
        Event lo_event2{
            .mv_timeout = 2,
        };
        mt_eventQueue.push(lo_event1);
        mt_eventQueue.push(lo_event2);
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      只要您的比较器函数不是functor,您应该在std::priority:queue 的构造函数中传递您的比较器函数。

      std::priority_queue<Event, std::vector<Event>, decltype(&CompareEvents)> mt_eventQueue(CompareEvents);
      

      如果你的比较器是这样的

      struct CompareEvents
      {
          bool operator()(const Event& a, const Event& b) {
              return a.mv_timeout < b.mv_timeout;
          }
      }
      

      您可以在不指定函子的情况下创建队列,只要它会由CompareEvents 的默认构造函数推导出来,(如here 所述)。

      std::priority_queue<Event, std::vector<Event>, CompareEvents> mt_eventQueue; //this works
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多