为何std::queue执行pop()后,front()获取的值仍能存在?
为什么队列清空后局部变量的值还存在?
这问题问到点子上了,核心是搞明白引用的作用和值拷贝的区别,咱们结合你的代码一步步说:
先看你的代码片段:
int main() { std::string val; { std::queue<std::string> q; q.push("one"); q.push("two"); q.push("three"); val = q.front(); q.pop(); q.pop(); q.pop(); std::cout << "is queue empty: " << boolalpha << q.empty() << '\n'; } std::cout << "val: " << val << '\n'; }
关键细节拆解:
q.front()确实返回队列首元素的引用,但你这里做的是val = q.front();——这是一个值拷贝操作。也就是说,你把队列里那个"one"字符串的内容,完完整整地复制到了val这个独立的std::string对象里。val和队列里的元素是两个完全分开的内存空间,互相不影响。- 之后的
q.pop()操作,只会销毁队列里的元素(包括原来的"one"),但这和val半毛钱关系都没有——val已经拿到了自己的拷贝,它的生命周期是从main函数开始到结束,哪怕包含队列的那个大括号作用域结束、队列被销毁,val依然好好地活着,保存着之前拷贝的"one"。
反过来想如果是引用会怎样?
要是你把val声明成引用:std::string& val = q.front();,那情况就完全不同了——val会变成队列首元素的别名,当你pop之后,原来的元素被销毁,val就成了悬空引用,再访问它就是未定义行为(可能输出乱码、崩溃,或者看似正常但实际上有隐患)。但你的代码里是值拷贝,所以完全安全。
总结一下:你存到局部变量的不是引用本身,而是引用指向的值的拷贝,所以队列的销毁不会影响这个局部变量~
内容的提问来源于stack exchange,提问作者r18ul




