Question regarding the << operator

J

Juri

Hi all,

I have a question regarding the << operator.
I wrote a simple queue class, which contains add(char), del() and empty() functions.
They works fine.
Now I want its output.
If I write the following way, it gives me the correct output.

while(!q1.empty()){ // This prints "abc"
cout<<q1.del();
}

However, if I write the following way, it gives me the wrong output sequence.
cout<< q.del() << q.del() << q.del(); // This prints "cba"

Can someone explain how the operator is working in these cases?
Please refer to the following main.
Thanks.

J

**********************************************************************8
int main()
{
queue q;
q.add('a');
q.add('b');
q.add('c');

cout<< q.del() << q.del() << q.del(); // This prints "cba" <-- Wrong!
cout<<"\n";

queue q1;
q1.add('a');
q1.add('b');
q1.add('c');

while(!q1.empty()){ // This prints "abc"
cout<<q1.del();
}
cout<<"\n";
return 0;
}
 
D

David Harmon

On 13 Jun 2004 20:43:40 -0700 in comp.lang.c++, (e-mail address removed)
(Juri) wrote,
However, if I write the following way, it gives me the wrong output sequence.
cout<< q.del() << q.del() << q.del(); // This prints "cba"

Note that the three calls to q.del() can occur in any order at the
convenience of the compiler, and the results held as temporary values.
After that, your operator<< does nothing remarkable.

If you want to control the order of evaluation, you must use some
language construct that introduces a "sequence point". The simplest
would be to make them three separate statements.
 
R

Rob Williscroft

Juri wrote in in
comp.lang.c++:
I have a question regarding the << operator.
I wrote a simple queue class, which contains add(char), del() and
empty() functions. They works fine.
Now I want its output.
If I write the following way, it gives me the correct output.

while(!q1.empty()){ // This prints "abc"
cout<<q1.del();
}

However, if I write the following way, it gives me the wrong output
sequence. cout<< q.del() << q.del() << q.del(); // This prints "cba"

The compiler is free to make each of the three 'q.del()' calls in *any*
order it sees fit. The reason its doing it in what you may think of as
/reverse/ order is probably because its faster to do so.

The only solution is to write:

cout << q.del();
cout << q.del();
cout << q.del();

Rob.
 
P

Partho Bhowmick

Rob Williscroft said:
Juri wrote in in
comp.lang.c++:


The compiler is free to make each of the three 'q.del()' calls in *any*
order it sees fit. The reason its doing it in what you may think of as
/reverse/ order is probably because its faster to do so.

The only solution is to write:

cout << q.del();
cout << q.del();
cout << q.del();

Rob.

I disagree. The << associates from left to right. What you expected to
happen should have happened. This seems like a bug.
 
V

Victor Bazarov

Partho said:
I disagree. The << associates from left to right. What you expected to
happen should have happened. This seems like a bug.


No, it's the specified behaviour. The expression involving overloaded
operator << is not the same as built-in arithmetic shift. Consider:

blah << one << two << three;

is in fact

operator << (operator << ( operator << (blah, one) , two ) , three)
^^^^ a
^^^^^^^^^^^^^^^^^^^^^^^ b
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ c

The order of evaluation between (a) and (one) is _unspecified_, the
order of evaluation between (b) and (two) is _unspecified_ , and the
order of evaluation between (c) and (three) is _unspecified_. That
means that (one), (two), and (three) can be evaluated in _any_order_.

That's why if the results of their execution (side effects) depend on
the order of evaluation, it is not recommended to have them in the
same expression.

Victor
 
R

Rob Williscroft

Partho Bhowmick wrote in @newssvr25.news.prodigy.com in comp.lang.c++:
I disagree. The << associates from left to right. What you expected to
happen should have happened. This seems like a bug.

Association has nothing to do with it, association only effects how the
compiler interprets the expression:

a op b op c

If 'op' is left to right becomes: ((a op b) op c)
If 'op' is right to left becomes: (a op (b op c))

Simple example:

int i = 1;

int f( int j ) { return j; }

int main()
{
i = i << f( 1 ) << f( 2 );
}

The compiler can rewrite this as:

int main()
{
int r1 = f( 1 );
int r2 = f( 2 );

int r3 = i << r1;
i = r3 << r2;
}

or it could rewrite it like this:

int main()
{
int r2 = f( 2 );
int r1 = f( 1 );

int r3 = i << r1;
i = r3 << r2;
}

However the Association rules prevent the compiler from rewriting it as:

int main()
{
int r1 = f( 1 );
int r2 = f( 2 );

int r3 = r1 << r2;
i = i << r1;
// effectivly i = i << ( f( 1 ) << f( 2 ) );
}


Note that in this simple case, because every thing can be done in
registers, just about every compiler is going to do what we
"intuitivly" expect:

int main()
{
register int r = i;
r <<= f( 1 );
r <<= f( 2 );
i = r;
}

Rob.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top