C++ std::queue does not want to push()
This is a simple class and simple test function:
#include <queue>
#include <string>
namespace {
using namespace std;
}
class NameStream {
queue<string> stream;
public:
string operator * () { return stream.front(); }
NameStream &operator ++(int) { stream.pop(); return *this; }
NameStream &operator ++() { stream.pop(); return *this; }
NameStream &operator <<(string name) { stream.push(name); }
operator bool() { return !stream.empty(); }
};
inline void nameStreamTest() {
NameStream &stream = *new NameStream;
stream << "hi" << "hey" << "hoy";
while (stream) {
printf("%s\n", (*stream++).c_str());
}
}
It falls in
NameStream &operator <<(string name) { stream.push(name); }
inside queue's push procedure, here is the stack beyond my code:
#0 0x000b5079 in std::deque<std::string, std::allocator<std::string> >开发者_如何学编程;::push_back at stl_deque.h:1055
#1 0x000b50f2 in std::queue<std::string, std::deque<std::string, std::allocator<std::string> > >::push at stl_queue.h:204
#2 0x000b511c in NameStream::operator<< at NameStream.h:24
#3 0x000b520f in nameStreamTest at NameStream.h:32
My experience fails in this case. What am I doing wrong?
P.S.:
NameStream &stream = *new NameStream;
Is used to clear off location of
stream
object at address (offset?) 0x7d (!) which causes same exception.
Put a return statement at the end of your function.
NameStream &operator <<(string name) { stream.push(name); return *this; }
Add: Not returning a valid reference/value (when needed) will cause a UB and that will cause hidden crashes or bad behavior which are often hard to debug (as in your case). So never ignore a compiler warning if it generates any.
It is failing as postfix operator ++
is having higher precedence than operator *
, so when for the last iteration of the loop is executed, you first pop
from the queue and then try to do front
by which time queue is empty. To solve this, the simplest way is to break it into two statements like:
while (stream) {
printf("%s\n", (*stream).c_str());
stream++;
}
It falls in
NameStream &operator <<(string name) { stream.push(name); }
You don't return *this
... by chaining the operator<<()
calls, the second and third one have no valid object address to work on.
You've got a number of problems in the code.
Missing return in
operator<<
(as pointed out by iammilind and others) which causes the runtime error that you observe. It can be corrected as follows:NameStream &operator <<(string name) { stream.push(name); return *this; }
Another problems is due to the sequence of calls in the body of your while loop which is:
- operator ++(int)
- operator * ()
Therefore in the last iteration you first
pop()
inoperator++(int)
and then try to callfront()
inoperator*()
on an empty queue which will cause a runtime error.The easiest way to fix it is to rewrite your while loop as follows.
while (stream) { printf("%s\n", (*stream).c_str()); ++stream; }
Memory leak. You call allocate a NameStream object using
new
, but never calldelete
. An easy solution is to allocate your stream object on stack:NameStream stream;
精彩评论