1

Here, I wrote a simple Queue Class Template:

#include "stdafx.h"
#include "iostream"
#include "conio.h"

template <class T> class Queue {
private:
    struct Node {
        T value;
        Node *next;
    };
    Node *first, *last;
public:

    Queue () { //Initialization
        first = 0;
        last = 0;
    };

    void push(T value) { //Put new value into Queue
        Node *p = new Node;
        p->value = value;

        if (!first) //If Queue is not empty
            first = p;
        else
            last->next = p;

        last = p; //Put the value to the last of the Queue
    };

    T get() { //Get the first value of the Queue
        return (first) ? first->value : NULL;
    };

    T pop() { //Take the first value out of Queue
        T result = first->value;
        Node *temp = first;
        first = first->next;
        delete temp;
        return result;
    };
};

int _tmain(int argc, _TCHAR* argv[])
{
    Queue<int> bag;
    bag.push(1); //Bag has value 1
    bag.push(2); //Bag has values: 1, 2

    std::cout << bag.get() << '\n' << bag.pop() << '\n' << bag.pop();
    _getch();
    return 0;
}

There is a problem - the output is:

0
2
1

/*
Correct output should be:
1
1
2
*/

When I debug the std::cout line, I found out that program call bag.pop() at the right most first, then the other bag.pop(), at last the bag.get(). Is that the right order?

  • 5
    The order is unspecified, if you need a specific order separate your cout statement into three pieces. `std::cout << bag.get() << '\n'; std::cout << bag.pop() << '\n'; std::cout << bag.pop();` – john Nov 21 '13 at 14:13
  • If you searched, you would find some answers: [cout << order of call to functions it prints?](http://stackoverflow.com/questions/2129230/cout-order-of-call-to-functions-it-prints/2129242#2129242) & [Order of evaluation of arguments using std::cout](http://stackoverflow.com/questions/7718508/order-of-evaluation-of-arguments-using-stdcout) – crashmstr Nov 21 '13 at 14:13
  • 1
    What if the template type `T` is not a pointer? Then you can't return `NULL` in the `get` function (unless `T` is a type that can be implicitly created from the integer `0`). – Some programmer dude Nov 21 '13 at 14:14

4 Answers4

4
T get() { //Get the first value of the Queue
    return (!first) ? first->value : NULL;
};

This is backwards. Drop the !. You are saying "if first is not non-null, (ie if first is null), use it.

That said, the order of evaluation of arguments to a function is unspecified (the compiler can evaluate the arguments in any order it feels like, as long as they are all done before the function itself starts). That is get(), pop() and pop() can be called in any order. Call them as separate statements:

int a = bag.get();
int b = bag.pop();
int c = bag.pop();
std::cout << a << b << c;
BoBTFish
  • 17,936
  • 3
  • 49
  • 73
  • Thank you. I fix that mistake but the program thrown exception because the first->value has no value to return after program call the other two `bag.pop()`. – Nguyễn Đức Long Nov 21 '13 at 14:16
0
T get() { //Get the first value of the Queue
    return (!first) ? first->value : NULL;
};

You return NULL if first is valid. This gets interpreted as zero. You should inverse your logic there.

luk32
  • 15,002
  • 33
  • 58
0

yeah, it's unspecified when calculate function of argument. take this simple test, you will get what's that mean.

#include <iostream>
int b(void) {std::cout<<3<<std::endl; return 3;}
int c(void) {std::cout<<4<<std::endl; return 4;}
int main(int argc, char *argv[])
{
  int d = b() + c();
  std::cout<<d<<std::endl;
  return 0;
}

so you will get 3 4 5 or 4 3 5.

DarkHorse
  • 161
  • 1
  • 12
-1

first look at : http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/

std::cout take value from left to right.

Dave
  • 51
  • 1
  • 5
  • 4
    It outputs the results from left to right. It evaluates its operands in an unspecified order, which is what the OP is asking about. – chris Nov 21 '13 at 14:19