队列为空时priority_queue pop()和top()的C ++行为

时间:2019-01-25 15:30:04

标签: c++

C ++ 11。

如果我尝试从空的pop开始priority_queue,,则会收到编译时错误。具体来说,

#include <iostream>
#include <queue>

int main()
{
    std::priority_queue<int> pq;
    int x = pq.pop();
    std::cout << x << std::endl;
}

产生编译时错误:

In function 'int main()': 7:20: error: void value not ignored as it ought to be

我很惊讶这是一个编译时错误,而不是运行时错误,但这是另一次讨论。

我不明白为什么top方法不会做同样的事情。实际上,如果我们将pop更改为top,则代码实际上会编译并运行(尽管输出是bizzare)。具体来说,

#include <iostream>
#include <queue>

int main()
{
    std::priority_queue<int> pq;
    int x = pq.top();
    std::cout << x << std::endl;
}

此代码可以正常编译,运行和退出,但不产生任何输出!它实际上不打印任何内容。我不知道怎么回事。

这是我的问题:

  1. 如果pop为空,是否定义了toppriority_queue的行为?我没有提到这种情况in the docs

  2. 在第二种情况下怎么没有输出? top返回一个常量引用。因此,它必须指向某物。我可以想象它只是将它指向的任何内存解释为整数。但这似乎没有发生。似乎整数的行为类似nullptr

3 个答案:

答案 0 :(得分:3)

int x = pq.pop();

pop返回void。将void分配给变量的格式不正确。如错误所示:

 void value not ignored as it ought to be

另一方面:

int x = pq.top();

将整数分配给变量的格式正确。

  
      
  1. 如果priority_queue为空,是否定义了pop和top的行为?
  2.   

不。该行为是未定义的(对于std::priority_queue<int>。该行为可能是为其他基础容器定义的。)

  
      
  1. 第二种情况下怎么没有输出?
  2.   

行为是不确定的。

  

具体地说,我认为UB意味着您不知道变量x的含义。

是正确的,但是对UB的描述不完整。 UB意味着您无法预测有关程序行为的任何信息。

答案 1 :(得分:3)

在空的priority_queue上调用std::priority_queue::top的行为取决于基础容器。

  

引用顶部元素,就像通过调用c.front()

获得的一样

如您的代码所示,默认参数std::vector被用作基础容器,并且在空容器上调用std::vector::front的行为是不确定的。这意味着一切皆有可能。

  

在空容器上调用前台是不确定的。

std::priority_queue::pop类似,它将在基础容器上调用pop_back;对于std::vector::pop_back,在空容器上调用它也是UB。

  

在空容器上调用pop_back是未定义的。

最后,std::priority_queue::pop不返回任何内容;这就是int x = pq.pop();不起作用的原因(错误消息试图告诉您)。

答案 2 :(得分:3)

您错误地使用了priority_queuepop()上的From the docs

  

返回值
  (无)

但是,您尝试将其绑定到整数变量。与

相同
void f() {};

int n = f();

,没有任何意义。此外,对于

int x = pq.top();

我们再次得出from the docs的结论

  

引用顶部元素,就像通过调用c.front()

获得的一样

因此,行为取决于基础容器的front()成员函数。在您的示例中,这是默认值std::vector,因此是from the docs

  

返回对容器中第一个元素的引用。
  在空容器上调用front是未定义的。

您在UB土地上,因此不要尝试从程序输出中得出任何结论。