Zero.Arcan
Zero.Arcan

Reputation: 51

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.

Upvotes: 4

Views: 2307

Answers (4)

iammilind
iammilind

Reputation: 69988

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.

Upvotes: 6

vitaut
vitaut

Reputation: 55564

You've got a number of problems in the code.

  1. 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; }
    
  2. Another problems is due to the sequence of calls in the body of your while loop which is:

    1. operator ++(int)
    2. operator * ()

    Therefore in the last iteration you first pop() in operator++(int) and then try to call front() in operator*() 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;
    }
    
  3. Memory leak. You call allocate a NameStream object using new, but never call delete. An easy solution is to allocate your stream object on stack:

    NameStream stream;
    

Upvotes: 0

Naveen
Naveen

Reputation: 73443

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++;
    }

Upvotes: 2

Tony Delroy
Tony Delroy

Reputation: 106106

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.

Upvotes: 0

Related Questions