Re: Guarantee of side-effect free assignment
On Oct 7, 9:36 pm, James Dennett <jdenn...@acm.org> wrote:
Alf P. Steinbach wrote:
* James Dennett:
Alf P. Steinbach wrote:
I can find no such guarantee in the standard. It
seems the compiler is free to rewrite
p = new S();
as
p = operator new( sizeof( S ) );
new( p ) S();
What would grant the compiler freedom to deviate in such an
observable way from the semantics of the abstract machine (in
which, I hope it is clear, the rhs of an assignment is evaluated
before its result -- if there is one -- is assumed to be known).
That rule is not only not clear, it seems to be non-existent.
It seems to follow simple logic. The value of an expression
is determined by evaluating that expression.
The same simple logic says that in "j = ++i;", the ++i must
precede the assignment. The standard quite clearly says that
this is *not* the case; that an expression has both a value and
side effects, and that the two are more or less independent.
In this case, there are sequence points as part of the
evaluation of the new expression (in particular, at the start
and end of the call to operator new, and at the start and end
of the call to a constructor).
The call to the allocator function definitely introduces a
sequence point. The call to the allocator function must also
precede the assignment, since the compiler can have no way of
knowing what the value of the expression is until this call has
occured. The "call" to the "constructor" of a built-in type
(e.g. "new int(42)") does NOT introduce a sequence point, and at
any rate, the standard does not clearly say that the call to the
constructor is part of the "value" of the expression; it would
seem logically to be a side effect, so it's sequence points
aren't relevant.
So the issue is whether the assignment side-effect can be
moved to before those sequence points.
We agree that such a move is observable. I claim that it
violates the notion of evaluation of an expression (a notion
so fundamental that it's not specified by 14882, as the
relevant aspects of it are common to an entire field).
And how does this not apply to the case of "j = ++ i;" Whether
the modification of i occurs before or after the assignment to j
is potentially observable, e.g. through an asynchronous signal.
An expression can result in a value, and can cause side effects.
As far as I can tell, all that is required (of the abstract
machine) is that those side effects occur before the next
sequence point. That is certainly the traditional
interpretation.
The question is, of course, whether the call to the constructor
is a side effect, or whether it is a necessary part of
evaluating the value. The most intuitive interpretation would
be that it is a side effect.
Abstractly the evaluation of the RHS is performed in order
to determine the value to assign to the LHS. The assignment
clearly, abstractly, cannot be performed until the value to
assign is known; that much is clear from the definition in
the standard of what assignment does. We have the following
actions:
* Call operator new
* Call the constructor
* Assign the result of the expression to p
Side-effects within operator new and the constructor are
constrained by sequence points to taking effect after those
(special) functions are entered and before they return.
The assignment is (in terms of the abstract machine) constrained
by the definition of assignment, which requires that the value
of the expression be determined.
Again, I refer to the expression "j = ++ i". If i and j are
initially 0, the above analysis would mean that an asynchronous
signal could see: i==0 && j==0, i==1 && j==0 or i==1 && j==1,
but never i==0 && j==1. This is contrary to the traditional
interpretation of what is allowed in C.
Of course, all of these requirements are being radically
changed, in order to take threading into account. So the
actual guarantees will change (although hopefully with no effect
on currently legal single threaded C++ programs).
[...]
Indeed, and the latest drafts use a different notion of
sequencing to avoid these discussions (and many more that
crop up when we start to consider multi-threading, as that
makes much more behavior potentially observable).
However, note that there is a difference also between the
"side-effects" of expression evaluation and the very function
calls which make up the expression evaluation. i++ has the
side-effect of incrementing i; calling a function is not a
mere side-effect, as it affects the value of the expression.
Only if the return value is used in the expression. And a
constructor of a built-in type isn't a function call, either.
In other words, evaluation of expressions in C++ has two
aspects: (1) determining the value of that expression, and
(2) side-effects (which may modify state, or have otherwise
consequences). The side-effects can be reordered so long
as the semantics of the abstract machine (i.e., the specification
of what things mean in C++) is not violated. Reordering an
assignment to before the value to assign is evaluated is a
violation of these semantics.
I think the above is somewhat of a misstatement. ?5/4 says
quite clearly: "Except where noted, the order of evaluation of
operands of individual operators and subexpressions of
indivitual expressions, AND THE ORDER IN WHICH SIDE-EFFECTS TAKE
PLACE, is unspecified." This refers to the abstract machine:
side effects are not required to take place in the same order
the corresponding sub-expressions are evaluated, except where
noted. What Alf and I can't find is where this is noted for the
side effect of calling a constructor (or executing the
initialization of a built-in type) in a new expression.
[...]
Looking over a current draft would be useful then, to check
that the changes more clearly express what we want.
I'll do so. It's possible that the issue has been addressed;
it's (vaguely) related to the problem of double checked locking.
(Except that if it is addressed in that context, the tendency
would be to say that it isn't guaranteed.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]