如何解决C ++列表/队列的顶部返回值
我有一个C ++代码,如下所示:
#include <iostream>
#include <queue>
#include <list>
using namespace std;
int main(){
priority_queue<pair<int,int>> q;
q.push({8,8});
q.push({19,19});
q.push({23,23});
while (q.size() > 0){
auto& cur = q.top();
q.pop();
cout << cur.first << " " << cur.second << " "; // returns 19 19 8 8 8 8
}
cout << endl;
list<pair<int,int>> newq;
newq.push_back({19,19});
newq.push_back({8,8});
newq.push_back({23,23});
while (newq.size() > 0){
auto& cur = newq.front();
newq.pop_front();
cout << cur.first << " " << cur.second << " "; // returns 19 19 8 8 23 23
}
cout << endl;
return 0;
}
使用list
与auto&
对auto
进行迭代会产生相同的输出。但是我试图理解为什么如果在遍历优先级队列时使用auto&
时输出错误。如果将其更改为auto
,则输出正确:
priority_queue<pair<int,23});
while (q.size() > 0){
auto cur = q.top();
q.pop();
cout << cur.first << " " << cur.second << " "; // returns 23 23 19 19 8 8
}
cout << endl;
感谢您的澄清!
解决方法
auto& cur = q.top();
q.pop();
auto &
在这里不起作用而auto
起作用的原因是,通过auto &
,您可以在队列top()
处获得对对象的引用。
...然后在下一行中,立即将队列顶部的那个对象删除并销毁,从而留下悬挂的引用。
从那时起使用该引用会导致未定义的行为。
相反,使用auto
复制对象,并且在原始对象被销毁后副本仍然存在。
与std::list
一起使用时,类似的错误当然可能不会产生明显的错误结果,但仍然是未定义的行为。 “未定义的行为”的确切含义是:任何事情都可能发生。包括纯粹出于偶然而获得预期结果。一个好的静态分析工具,例如valgrind,应该能够捕获此错误。
操作时:
auto& cur = q.top();
您正在引用priority_queue
中的top元素。但是当您这样做时:
q.pop();
此元素已删除,并且对该元素的所有引用(包括cur
)都处于悬空状态。任何尝试从cur
读取的内容,例如:
cout << cur.first << " " << cur.second << " ";
将调用未定义的行为,该行为可以做任何事情,包括给出您观察到的结果。
正在做
auto cur = q.top();
很好,因为您正在复制top元素。从q
中删除该元素不会影响副本。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。