简体   繁体   English

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

[英]C++ Behavior of priority_queue pop() and top() when queue is empty

C++11. C++11。

If I try to pop off of an empty priority_queue, then I get a compile time error.如果我尝试从空的priority_queue, pop priority_queue,则会出现编译时错误。 Specifically,具体来说,

#include <iostream>
#include <queue>

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

yields the compile-time error:产生编译时错误:

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

I am surprised that this is a compile-time error and not a runtime error, but that is another discussion.我很惊讶这是一个编译时错误而不是运行时错误,但这是另一个讨论。

What I don't understand is why the top method wouldn't do the same thing.我不明白的是为什么top方法不会做同样的事情。 In fact, if we change pop to top the code actually compiles and runs (albeit with a bizzare output).事实上,如果我们将pop更改为top代码实际上会编译并运行(尽管输出有点奇怪)。 Specifically,具体来说,

#include <iostream>
#include <queue>

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

This code compiles, runs, and exits normally, but produces no output!此代码正常编译、运行和退出,但不产生任何输出! It literally prints nothing.从字面上看,它什么也不打印。 I do not understand how that can be.我不明白怎么会这样。

Here are my questions:以下是我的问题:

  1. Is the behavior for pop and top defined if the priority_queue is empty?如果priority_queue为空,是否定义了poptop的行为? I don't see any mention of this condition in the docs .在文档中没有看到任何提及这种情况。

  2. How is there no output in the second case?第二种情况怎么没有输出? top returns a constant reference. top返回一个常量引用。 So it must be pointing at something.所以它一定是在指向某个东西。 I would imagine that it simply interprets whatever piece of memory it is pointing to as an integer.我想它只是将它指向的任何一段内存解释为一个整数。 But that doesn't seem to be happening.但这似乎并没有发生。 It seems like the integer is behaving something like a nullptr .似乎整数的行为类似于nullptr

int x = pq.pop();

pop returns void . pop返回void It is ill-formed to assign void to a variable.void分配给变量是不正确的。 As the error says:正如错误所说:

 void value not ignored as it ought to be

On the other hand:另一方面:

 int x = pq.top();

It is well-formed to assign an integer to a variable.将整数分配给变量是格式良好的。

  1. Is the behavior for pop and top defined if the priority_queue is empty?如果 priority_queue 为空,是否定义了 pop 和 top 的行为?

No. The behaviour is undefined (for std::priority_queue<int> . The behaviour may be defined for other underlying containers).否。行为未定义(对于std::priority_queue<int> 。行为可以为其他底层容器定义)。

  1. How is there no output in the second case?第二种情况怎么没有输出?

The behaviour is undefined.行为未定义。

Specifically, I thought that UB means that you don't know what you get in the variable x.具体来说,我认为 UB 意味着你不知道你在变量 x 中得到了什么。

That's correct, but an incomplete description of UB.这是正确的,但对 UB 的描述不完整。 UB means that you cannot predict anything about the behaviour of the program. UB 意味着您无法预测有关程序行为的任何信息。

The behavior of calling std::priority_queue::top on an empty priority_queue depends on the underlying container.在空的priority_queue上调用std::priority_queue::top的行为取决于底层容器。

Reference to the top element as if obtained by a call to c.front()对顶部元素的引用,就像通过调用c.front()

As your code showed, the default argument std::vector is used as the underlying container, and the behavior of calling std::vector::front on empty container is undefined;正如您的代码所示,默认参数std::vector用作底层容器,并且未定义在空容器上调用std::vector::front的行为; which means anything is possible.这意味着一切皆有可能。

Calling front on an empty container is undefined.在空容器上调用 front 是未定义的。

It's similar for std::priority_queue::pop , which will call pop_back on the underlying container;它类似于std::priority_queue::pop ,它将在底层容器上调用pop_back for std::vector::pop_back calling it on an empty container is UB too.对于std::vector::pop_back在空容器上调用它也是 UB 。

Calling pop_back on an empty container is undefined.在空容器上调用 pop_back 是未定义的。

At last, std::priority_queue::pop returns nothing;最后, std::priority_queue::pop什么都不返回; that's why int x = pq.pop();这就是为什么int x = pq.pop(); won't work (as the error message tried to tell you).不会工作(因为错误消息试图告诉你)。

You are using the priority_queue incorrectly.您错误地使用了priority_queue From the docs on pop() : 来自pop()的文档

Return value返回值
(none) (没有任何)

Yet you try to bind that to an integral variable.然而,您尝试将其绑定到一个整数变量。 This is the same as这与

void f() {};

int n = f();

and doesn't make any sense.并且没有任何意义。 Furthermore, for此外,对于

int x = pq.top();

we again conclude from the docs that我们再次 从文档中得出结论

Reference to the top element as if obtained by a call to c.front()对顶部元素的引用,就像通过调用c.front()

So the behavior depends on the front() member function of the underlying container.所以行为取决于底层容器的front()成员函数。 In your example, that's the default one, std::vector , hence from the docs :在您的示例中,这是默认的std::vector ,因此来自 docs

Returns a reference to the first element in the container.返回对容器中第一个元素的引用。
Calling front on an empty container is undefined.在空容器上调用 front 是未定义的。

There you are in UB land, hence don't try to conclude anything from the output of your program.你在 UB 领域,因此不要试图从你的程序输出中得出任何结论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM