Actually, it depends. The ones overloaded to take basic types as arguments are member functions of ostream and as such take one argument. Any custom overloads will be non-member functions and thus take 2 arguments.Quote:
Originally Posted by Graham
Printable View
Actually, it depends. The ones overloaded to take basic types as arguments are member functions of ostream and as such take one argument. Any custom overloads will be non-member functions and thus take 2 arguments.Quote:
Originally Posted by Graham
<super-nickpicky> Actually, even the member functions take two arguments, because this is implicitly passed to member functions. </super-nickpicky>Quote:
Originally Posted by HighCommander4
All right, point taken. ;)Quote:
<super-nickpicky> Actually, even the member functions take two arguments, because this is implicitly passed to member functions. </super-nickpicky>
Output is: 10 10 12 12Quote:
Originally Posted by dullboy
Surely
cout << var1 << var++ << ++var1 << var1;
is the same as
cout.operator << (var1).operator << (var1++).operator << (++var1).operator << (var1);
which is the same as
cout.operator << (var1);
cout.operator << (var1++);
cout.operator << (++var1);
cout.operator << (var1);
I don't see any potential undefined results here?
Although the original line of code appears to be one statement, it is actually four seperate function calls in a defined order.
Or am I missing something?
Now
foo(var1, var1++, ++var1, var1);
would definitely be undefined.
It is not the same. The original statement has a single sequence point (at the semicolon), before which it modifies the stored value of var1 three times. This is not allowed, as has been pointed out previously. The four function calls are not in a "defined" order - at least, the evaluation of the arguments to those functions has no defined order, and that's where the problem lies.Quote:
Originally Posted by JohnW@Wessex
Recasting it into four statement introduces three new sequence points - var1 is never modified more than once between any two of these sequence points, the sequence points impose an ordering on the argument evaluation, and so the recast version is fine.
By splitting up into separate statements, you are forcing an evaluation order and allowing multiple updates to the value (one per sequence point), neither of which hold in the single-statement form.
The point about sequence points is that they are defined places where all expressions up to that point have been fully evaluated and all side-effects have completed. Between sequence points, there are no guarantees.
C++ standard, 1.9/7:
I've quoted chapter and verse about this from the standard further up the thread. For the umpteenth time, the "cout" statement in the original post invokes undefined behaviour.Quote:
[...] At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.
Yes, there can be multiple function calls executed in a single statement.
And the standard says that only one of these may modify a variable.
I don't know what the defined behaviour is when a variable appears in a statement multiple times and is modified exactly once (which could be a non-const function being called on it).
Note that while the behaviour is undefined, the code compiles.
And maybe the reason why I don't know the behaviour of the above is doing so would make the code look ambiguous. The only times we "know" the effect of is using post-increment ++ once inside a statement, whereby the object is modified but the old value is used.
Now, to be nitpicky, in this statement:
os is modified 3 times, because << is a non-const function (and so it should be). Yet the behaviour is well defiined.Code:os << a << b << c;
Is this undefined?
I think here i should always be 3.Code:int i=0;
cout << ++(++(++i));
In this statement though:
Now i++ will return 0 and the left hand ++ will modify that 0 to 1 but will it be modifying i or a temp? operator++(int) normally returns a copy of the object that was updated. Will it compile? What will be the value of i at the end of the statement?Code:int i=0;
cout << (++(i++))++;
If you go back to post #13, where I posted the quote from the standard, you'll see that it says [...]a scalar object[...]. Which opens the question of whether that paragraph also applies to scalar members of objects in expressions.Quote:
Originally Posted by NMTop40
Scalar means a basic type?
Pretty much, yes.Quote:
Originally Posted by HighCommander4
I get the point about,
"You are not allowed to modify the stored value of a variable more than once between sequence points"
Fine. Rules are made to follow.
But,
What is a sequence point? Is it the semi-colon?
Why is the sequence point so releavent?
Why is it that,
the behaviour is undefined if i try to do as in POST#1,
but defined if i try....
What i mean is what happens behind the scenes, with respect to the sequence points?Code:++obj;
obj = obj+7;
And yes, i did read this...
Quote:
The point about sequence points is that they are defined places where all expressions up to that point have been fully evaluated and all side-effects have completed. Between sequence points, there are no guarantees.
I followed the link and found about sequence points that:
Quote:
However, there's a sequence point after the evaluation of the arguments but before the call actually occurs.
Is a sequence of function calls, with only one (or zero) side effect at each function call.Code:cout<<var1<<" "<<var1++<<" "<<++var1<<" "<<var1++;
so, the result should be defined? And it should be 10 10 12 12
Am i wrong?
Just what I thought!Quote:
Originally Posted by SuperKoko
The 'output is undefined' camp seem to have gone quiet.
Any response to this, guys?