C ++的新手,我想如果我定义一个容器并将其类型指定为string
,那么它应该从string
中出来而不必大惊小怪,我想拥有一个引用变量别名这个字符串。显然,我在这里错过了一些东西,因为编译器抱怨它无法将void转换为字符串。有人可以帮忙澄清一下吗?谢谢。
#include <queue>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
std::queue<std::string> myqueue;
myqueue.push("val1");
myqueue.push("val2");
while (!myqueue.empty()) {
std::string & s = myqueue.pop();
std::cout << s << endl;
}
}
答案 0 :(得分:4)
那是因为std::queue::pop
没有返回任何内容(无效)。
如果要访问第一个元素然后将其删除,则应使用std::queue::front
,然后使用std::queue::pop
。
while (!myqueue.empty()) {
std::string & s = myqueue.front();
std::cout << s << endl;
myqueue.pop();
}
我将myqueue.pop();
移到了std::cout << s << endl;
之后,以避免悬挂引用(对不再存在的对象的引用)。
答案 1 :(得分:3)
master
的返回类型为queue::pop
,仅删除第一个元素。如果要保留其值,请首先使用void
对其进行检索,并应按值而不是按引用保留它,因为它弹出时,对其的引用就变得悬而未决。
front()
答案 2 :(得分:1)
std::queue::pop()
不返回任何内容。它只是删除队列的第一个元素。您必须使用std::queue::front()
获取对第一个元素的引用(并将其存储在s
中),然后调用std::queue::pop()
从队列中的之后您已经使用过s
,而您不再需要它。
在调用s
之后不要使用存储在std::queue::pop()
中的引用,这很重要,因为在后台,std::queue
包装了一个std::dequeue
对象和{{1} }在其上调用std::dequeue::pop_first()
。 std::queue::pop()
的文档页面指出:
迭代器和对已擦除元素的引用均无效。
您的代码可能是:
std::dequeue::pop_first()
答案 3 :(得分:0)
pop()
在使用队列中的元素时,而不是:
pop()
的元素的引用,或者front()
复制元素,以避免悬而未决的参考场景,您可以将front()
元素移出队列,并立即在队列中调用pop()
。例如
#include <iostream>
#include <queue>
#include <string>
#include <utility>
template<typename T>
T removeFrontFromOfQueue(std::queue<T>& q) {
T front = std::move(q.front());
q.pop();
return front; // Should be able to rely on NRVO, and if not, a move ctor.
}
int main() {
std::queue<std::string> myqueue({"val1", "val2"});
while (!myqueue.empty()) {
std::string s = removeFrontFromOfQueue(myqueue);
std::cout << s << " ";
} // val1 val2
}
如以下问答所述,
这很安全。
front()
对象的引用的生存期或者,如果您选择存储对队列front()
的引用,请考虑在队列上调用pop()
之前限制引用的生存期。例如:
while (!myqueue.empty()) {
{
const std::string& s = myqueue.front();
std::cout << s << " ";
}
myqueue.pop();
} // val1 val2