0

I have the following implementation of Queue:

#include <iostream>
#include <memory>
#include <cstddef>

template<typename T>
class Queue
{
    std::unique_ptr<T[]> q_ptr;
    int front_idx = -1;
    int back_idx = -1;
    int capacity = 0;
public:
    Queue(std::size_t space)
    {
        q_ptr = std::unique_ptr<T[]>(new T[space]);
        capacity = space;
    }
    void push(T value);
    void pop();
    T front() const;
    T back() const;
    std::size_t size() const;
};

template<typename T>
void Queue<T>::push(T value)
{
    if(front_idx == -1)
    {
        front_idx++;
    }
    if(back_idx - front_idx + 1 == capacity)
    {
        std::cerr << "Queue full\n";
        return;
    }
    q_ptr[++back_idx] = value;
}

template<typename T>
void Queue<T>::pop()
{
    if(front_idx == -1)
    {
        std::cerr << "Empty queue\n";
        return;
    }
    q_ptr[front_idx++] = T{};
}

template<typename T>
T Queue<T>::front() const
{
    return q_ptr[front_idx];
}

template<typename T>
T Queue<T>::back() const
{
    return q_ptr[back_idx];
}

template<typename T>
std::size_t Queue<T>::size() const
{
    if(front_idx == -1)
    {
        return 0;
    }
    else
    {
        return back_idx - front_idx + 1;
    }
}

int main()
{
    Queue<int> q1{20};
    std::cout << "Queue size initial: " << q1.size() << "\n";
    q1.pop();
    for(int i = 0; i < 23; i++)
    {
        q1.push(i);
    }
    std::cout << "Queue size: " << q1.size() << "\n";
    std::cout << "Queue front: " << q1.front() << "\n";
    std::cout << "Queue back: " << q1.back() << "\n";
    q1.pop();
    std::cout << "Queue size: " << q1.size() << "\n";
    std::cout << "Queue front: " << q1.front() << "\n";
    q1.pop();
    std::cout << "Queue size: " << q1.size() << "\n";
    std::cout << "Queue front: " << q1.front() << "\n";
    q1.push(12);
    std::cout << "Queue size: " << q1.size() << "\n";
    std::cout << "Queue back: " << q1.back() << "\n";
}

My problem is with the following statement in main:

std::cout << "Queue size initial: " << q1.size() << "\n";

When I run the code, the above statement gets printed in the right place on most occasions (i.e. as the first line in the output). But sometimes, it gets printed after the pop() and for loop under it, like this:

Empty queue
Queue full
Queue full
Queue full
Queue size initial: 0
Queue size: 20
Queue front: 0
Queue back: 19
Queue size: 19
Queue front: 1
Queue size: 18
Queue front: 2
Queue size: 19
Queue back: 12

I am trying to figure out the reason for such an inconsistent behavior. I am using Eclipse Cpp Photon IDE with minGW GCC. Kindly provide guidance.

skr
  • 914
  • 3
  • 18
  • 35
  • 1
    What exactly did you observe when debugging that code line by line? – πάντα ῥεῖ Sep 09 '18 at 14:55
  • 2
    `cout` is usually buffered, `cerr` usually isn't. Use the same stream if the order is important (or disable buffering, or flush after every line maybe). – Mat Sep 09 '18 at 14:57
  • I observed that the output didn't appear on the screen until I reached `for` loop. I always used to use `std::endl`. But recently switched to using `\n`, since `std::endl` is more expensive. – skr Sep 09 '18 at 15:02

1 Answers1

4

The empty and full queue messages are being written to std::cerr not std::cout, which are different streams. In particular, cerr is typically unbuffered (ie when you write to it, each line will be output immediately) where cout is typically buffered (it won't be output until the buffer is full).

The accepted answer for this question discusses buffering in some detail.

James Aylett
  • 3,332
  • 19
  • 20