【问题标题】:priority queue in C++ with custom class and lambda expression具有自定义类和 lambda 表达式的 C++ 中的优先级队列
【发布时间】:2015-07-22 20:35:58
【问题描述】:

我正在学习如何在 C++ 中使用 STL。我正在尝试使用std::priority_queue 实现堆。这是我的尝试:

#include<vector>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<functional>
using namespace std;

struct data {
    int first;
    int second;
};

class compare {
public:
    bool operator()(data &a ,data &b)
    {
         if(a.first < b.first) return true;
         else false;
    }
};

int main()
{   
    priority_queue <data , vector<data>, compare> heap;
    data temp2[] = { {5,19},{2,7},{90,9},{12,6} };

    for(int i = 0; i < 4; ++i)
    {       
       heap.push(temp2[i]);
    }

    while(heap.empty() == false)
    {
        cout << heap.top().first << endl;;
        heap.pop();
    }       
}

当我在 Visual Studio 2012 上运行此代码时。它在推送第二个元素时崩溃。错误如下:

Program: C:\WINDOWS\system32\MSVCP110D.dll
File: c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm
Line: 2463
Expression: invalid operator<

但是当我在 ideone 中运行相同的代码时,它可以工作,但输出错误。 Ideone link

1.谁能指出我哪里出错了?

在同一个问题中再添加一个问题:

2.如何写 this 的 lambda 表达式而不是使用 compare 函数?

【问题讨论】:

    标签: c++ stl priority-queue


    【解决方案1】:

    您不应忽略编译器发出的警告:

    warning C4715: 'compare::operator()' : not all control paths return a value
    

    这是因为else false; 不返回任何内容,它只是计算表达式false 并丢弃结果。应该是else return false;


    当然,更简单的选择是直接说return a.first &lt; b.first;


    回复您更新的问题:

    在这里使用 lambda 不会给您带来太多好处,因为您需要在初始化 heap 时将仿函数的类型指定为 std::priority_queue 的模板参数,并将仿函数本身指定为构造函数的参数(在使用compare 的版本中,函子是默认构造的;lambdas 不是默认构造的)。

    但是,既然你问了,那就是:

    #include <iostream>
    #include <queue>
    #include <vector>
    
    struct data
    {
       int first;
       int second;
    };
    
    int main()
    {
       auto cmp = [](const data& a, const data& b) { return a.first < b.first; };
    
       // For Visual C++ 2013 and beyond:
       // std::vector<data> temp = {{5, 19}, {2, 7}, {90, 9}, {12, 6}};
       // std::priority_queue<data, std::vector<data>, decltype(cmp)> heap{cmp, std::move(temp)};
    
       // For Visual C++ 2012 (doesn't support list-initialization for non-aggregates):
       data temp[] = {{5, 19}, {2, 7}, {90, 9}, {12, 6}};
       std::priority_queue<data, std::vector<data>, decltype(cmp)> heap(std::begin(temp), std::end(temp), cmp);
    
       while(!heap.empty())
       {
          std::cout << heap.top().first << '\n';
          heap.pop();
       }
    }
    

    我对您的原始代码做了几处修改;在正确性 (const) 和效率方面将它们作为改进建议。

    【讨论】:

    • @RATHI 我已更新答案以解决您的第二个问题。但是,请记住,在 SO 上不赞成在原始问题中添加不相关的问题 - 第二个问题应该是一个单独的问题。
    【解决方案2】:

    您的比较函数在false 之前缺少return。这应该有效:

    class compare{
    public:
        bool operator()(data &a, data &b)
        {
            if (a.first < b.first) 
                return true;
            else 
                return false;
        }
    };
    

    VS 给出编译警告,但不是错误。正如巴里所指出的,这不是错误。有关更多详细信息,请参阅此 SO 答案 https://stackoverflow.com/a/1610454/3154588。 (我仍然认为这应该是一个编译错误,因为没有返回值的代码路径总是错误的——至少对于我编写的所有代码而言!)

    【讨论】:

    • 或者,只是return a.first &lt; b.first;
    • 因为它不应该是编译错误。 “从函数的末尾流出相当于没有值的返回;这会导致返回值的函数出现未定义的行为。” VS 确实告诉你 operator&lt; 是无效的,这很有帮助!
    • 感谢您的评论。是的,我发现这个SO answer 证实了你的说法。我期望并且更喜欢编译错误而不是警告。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多