Subj : Re: chaining cout with a changing object To : borland.public.cpp.borlandcpp From : "Benjamin Pratt" Date : Wed Sep 10 2003 06:29 pm Well, the problem here is that only the order in which the << operators are executed is defined (left-to-right). But the order in which the arguments are evaluated is not defined. In this case they are being evaluated from right-to-left. This is also the behavior for VC6 (which I also tried it on). You student has discovered the perils of undefined behavior. Let me see if I can explain it a little clearer. The standard does not define the order in which the _arguments_ are evaluated. Thus the compilier chooses to evaluate each of the arguments (the mystack.pop() statements) from right-to-left. The return values are stored (probably in a stack :) ). So the return values from right-to-left were 321. Now the << stream operators are evaluated. This is guarenteed to be evaluated from left-to-right. The leftmost 'mystack.pop()' statement was the last to be evaluated; its result was 1. So 1 is sent to cout. Then 2, the middle argument. Finally the first argument evaluated, 3, is sent to cout. You may be wondering why would a compiler vendor choose to evaluate arguments right-to-left when the << operator will be evaluated left-to-right. Because they can! :) Seriously, it is more effienct. Each of the arguments can be stored from right-to-left in a stack, resulting in the leftmost argument being on the top of the stack. Then when the << operators are evaluated, each argument is pulled off the stack and feed to the stream. Very simple and quick. Other methods would require FIFO techniques which are a bit slower. The bottom line however, is that the code you posted results in undefined behavior. On some compiliers it may work, on others not. Always best to steer clear of this. Never rely on order of _argument_ evaluation. A related example of undefined behavior is: int x = 5; myfunc(--x, ++x); What is passed to myfunc? 4,5 ? or 5,6 ? Doesn't matter; don't do it, don't rely on order of argument evaluation. "Taras Kentrschynskyj" wrote in message news:3f5fa1b0$1@newsgroups.borland.com... > > One of my students at the Royal Institute of Technology in > Stockholm, Sweden, draw my attention to the following: > He had written an integer stack class (linked list > implementation) with a pop operation returning the top item > (data in the first node of the list, deleting this node after > setting the top pointer to it's next), and tried the following: > > cout << mystack.pop() << mystack.pop() << mystack.pop(); > > If he had pushed 1, 2 and 3 on the stack, in that order, the > output was, unexpectedly: > 123 > looks like a recursive call.. whereas the following: > > cout << mystack.pop(); > cout << mystack.pop(); > cout << mystack.pop(); > > of course gave the expected output: > 321 > > I tried to track the first alternative, and found out that > all three function calls are accomplished before any output > in the chained statement. > The same is true if you use another member function that doesn't > change the object, e g get(int i), returning item no i in the > stack. In this case, however, if you chain cout: > > cout << mystack.geti(1) << mystack.geti(2) << mystack.geti(3); > > the output comes in the chain order, not the reverse order as > with the pop function. > > So, what is going on? How are the three return values saved > in the chained statement? How does the pointer settings affect > the order of the chained output? > .