Topic: Operator || precedence (and Copy ctors use of oper=)
Author: AllanW@my-dejanews.com
Date: 1998/12/21 Raw View
In article <368b949c.82054866@source.netcom.com>,
source@netcom.com (David Harmon) wrote:
>
> On 17 Dec 1998 17:51:41 GMT, sbnaran@localhost.localdomain.COM (Siemel
> Naran) wrote:
> >
> >On 15 Dec 1998 23:59:05 GMT, Francis Glassborow
> >>In article <755dp5$38k@news3.euro.net>, Martijn Lievaart
> >
> >>>short-circuiting rule.
> >>I always knew it as lazy evaluation.
> >
> >Interesting choice of word. The term "short-circuit" suggests
> >that the evaluation of the second thing is skipped if it is
> >not necessary to evaluate it. The term "lazy evaluation"
> >suggests that both things are both potentially evaluated, but
> >that as an optimization, the evaluation of one is deferred
> >until it is necessary.
>
> I don't buy that at all. "Short circuit" suggests that some failure has
> caused an low-resistance electrical connection to conduct excessive
> current, with lots of heat dissapated, smoke, and eventually fire unless
> a fuse blows first.
>
> "Lazy evaluation" suggests that not enough evaluation is done to
> determine the correct answer or that the necessary evaluation is only
> accomplished part of the time.
By your logic, a destructor ought to be called a recycler, because a
"destructor" is "A furnace or oven for the burning or carbonizing of
refuse; specif. (Sewage Disposal), a furnace (called in full refuse
destructor) in which the more solid constituents of sewage are burnt."
[Source: Webster's Revosed Inabridged Dictionary (1913)] Taken
literally, such an attachment would be both impractical and
cost-prohibitive for most modern computer systems.
> It ought to be called "conditional" or "sequential" evaluation.
The terms "short-circuit" and "lazy" are both analogies. If they
help to explain a concept, then they are useful. Naturally, they can
be taken too far.
Furthermore, "conditional evaluation" might be confused with
"conditional expression," which is something quite different in C++.
And "sequential evaluation" is already a computer science term,
meaning that statements are executed one at a time in order. This is
the default in so-called "high level" languages.
(No, "high level" language doesn't mean that you aren't allowed to
put a book about it on your desk. The term is yet another analogy.)
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: source@netcom.com (David Harmon)
Date: 1998/12/19 Raw View
On 17 Dec 1998 17:51:41 GMT, sbnaran@localhost.localdomain.COM (Siemel
Naran) wrote:
>
>On 15 Dec 1998 23:59:05 GMT, Francis Glassborow
>>In article <755dp5$38k@news3.euro.net>, Martijn Lievaart
>
>>>short-circuiting rule.
>>I always knew it as lazy evaluation.
>
>Interesting choice of word. The term "short-circuit" suggests
>that the evaluation of the second thing is skipped if it is
>not necessary to evaluate it. The term "lazy evaluation"
>suggests that both things are both potentially evaluated, but
>that as an optimization, the evaluation of one is deferred
>until it is necessary.
I don't buy that at all. "Short circuit" suggests that some failure has
caused an low-resistance electrical connection to conduct excessive
current, with lots of heat dissapated, smoke, and eventually fire unless
a fuse blows first.
"Lazy evaluation" suggests that not enough evaluation is done to
determine the correct answer or that the necessary evaluation is only
accomplished part of the time.
It ought to be called "conditional" or "sequential" evaluation.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: mtobler@no-spam-ibm.net (Michael J. Tobler)
Date: 1998/12/20 Raw View
In article <Q9uBjkBKQud2EwoT@robinton.demon.co.uk>,
francis@robinton.demon.co.uk says...
>
> In article <755dp5$38k@news3.euro.net>, Martijn Lievaart
> <nobody@orion.nl> writes
> >Yes, || is left associative but no, that doesn't mean that they are executed
> >left to right, they are, but that is a result of the special
> >short-circuiting rule.
> I always knew it as lazy evaluation.
A short circuit normally refers to evaluation of two or more things; the
expression is satisfied as soon as something within the expression holds
true, so the subsequent evaluations are unnecessary:
if( a == 10 || b == 12 || c == 14 )
Here, if 'a' is in fact '10', then the other expressions need not be
visited.
Lazy evaluation refers to the fact that evaluation of some statement is
deferred until required.
--
<<<<<<<<<< Blue Skies >>>>>>>>>>>
< Michael J. Tobler >
< mtobler@no-spam-ibm.net >
< remove "no-spam-" when replying >
<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/21 Raw View
In article <MPG.10e59d9cd6011521989ecc@news3.ibm.net>, Michael J. Tobler
<mtobler@no-spam-ibm.net> writes
>A short circuit normally refers to evaluation of two or more things; the
>expression is satisfied as soon as something within the expression holds
>true, so the subsequent evaluations are unnecessary:
>if( a == 10 || b == 12 || c == 14 )
>
>Here, if 'a' is in fact '10', then the other expressions need not be
>visited.
>
>Lazy evaluation refers to the fact that evaluation of some statement is
>deferred until required.
exactly, which in this case is for ever:)
Francis Glassborow Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jim.hyslop@leitch.com
Date: 1998/12/16 Raw View
In article <3696e603.162171104@source.netcom.com>,
source@netcom.com (David Harmon) wrote:
>
> On 15 Dec 1998 07:54:16 GMT, David Wieringa <wieringa@xroads.com> wrote:
[snip]
> >According to my C++ book (Bjarne's The C++ Programming Language), it
> >states that all but a few operators are left-associative. I take this
> >to mean that || is included and that multiple ||'s will be executed from
> >left to right.
>
> Sorry, that is not what it means. The difference can be rather subtle.
> Associativity is strictly about how parts are grouped, and has little to
> do with order of evaluation. The expressions:
> ( x / y ) / z and x / ( y / z )
> are different in an associative sort of way, but in either of them x, y,
> and z can all be individualy evaluated, in any order, before being
> combined.
Just to expand on this a little, if I may - say you have an operator OP (for
example, OP is operator +, operator -, whatever) and an expression
x OP y OP z
If the operator is left-associative, the expression will be the equivalent to:
(x OP y) OP z
If, OTOH, the operator is right-associative, the expresssion will be the
equivalent of:
x OP (y OP z)
As you can see, the final result can potentially be quite different between
the two orderings. As David's example shows, if OP is operator/ you will get
significantly different values.
--
Jim
Note to recruitment agencies: I delete unsolicited email from
recruitment agencies without reading it, so don't even bother.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain.COM (Siemel Naran)
Date: 1998/12/17 Raw View
On 15 Dec 1998 23:59:05 GMT, Francis Glassborow
>In article <755dp5$38k@news3.euro.net>, Martijn Lievaart
>>short-circuiting rule.
>I always knew it as lazy evaluation.
Interesting choice of word. The term "short-circuit" suggests
that the evaluation of the second thing is skipped if it is
not necessary to evaluate it. The term "lazy evaluation"
suggests that both things are both potentially evaluated, but
that as an optimization, the evaluation of one is deferred
until it is necessary. In the "short-circuit" interpretation,
both things are seen as seperate instructions; in the
"lazy evaluation" interpretation, both things are seen as
part of a single closure. The term "short circuit" seems to
offer a safer interpretation though:
if (p && *p=="hello") ;
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1998/12/17 Raw View
In article <Q9uBjkBKQud2EwoT@robinton.demon.co.uk>,
Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
>
> In article <755dp5$38k@news3.euro.net>, Martijn Lievaart
> <nobody@orion.nl> writes
> >Yes, || is left associative but no, that doesn't mean that they are executed
> >left to right, they are, but that is a result of the special
> >short-circuiting rule.
> I always knew it as lazy evaluation.
Are you sure you're not confusing it with something else. Lazy
evaluation generally means differing the evaluation of an expression
until its results are needed; I've never seen it used in a compiled
procedural language like C++. (On the other hand, it is widely used in
libraries -- copy on write is a form of lazy copy, for example.)
--
James Kanze GABI Software, S rl
Conseils en informatique orient objet --
-- Beratung in industrieller Datenverarbeitung
mailto: kanze@gabi-soft.fr mailto: James.Kanze@dresdner-bank.com
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David Wieringa <wieringa@xroads.com>
Date: 1998/12/15 Raw View
In a recent code walk-thru at work, someone suggested that different
compilers process logical OR's differently.
e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
that x will be evaluated before y or z.
They didn't disagree that if the first (or second) expression evaluated
to true that the compiler would ignore the remaining expressions.
Can someone solve this disagreement?
According to my C++ book (Bjarne's The C++ Programming Language), it
states that all but a few operators are left-associative. I take this
to mean that || is included and that multiple ||'s will be executed from
left to right.
True? or compiler dependent?
If so, can we assume that the compiler will stop evaluating expressions
at the first "true" it finds? (since any true of an OR expression
results in a true result)
BTW, we're using Sun's CC 4.2 C++ compiler.
Any _authoritative_ assistance is greatly appreciated,
Dave
While I'm at it... I was going to post another message for this one,
but I just realized I should have looked something up at work and I
forgot. (my books are at work and I don't have access to the usenet at
work) ...so I'll tag it on this message as an added bonus.
Subject: Copy Constructors use of Assignment Operator
During the same walk-thru it came up that one should not all the
classes' assignment operator from the copy constructor (i.e. copy
constructor of *this = sourceObject). Is there any validy to this?
If this is true, why doesn't the compiler catch this? (or do most of
them?)
Should one in fact duplicate the assignment code in the copy constructor
if this is what is needed?
Thanks again,
Dave
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jackklein@att.net (Jack Klein)
Date: 1998/12/15 Raw View
On 15 Dec 1998 07:54:16 GMT, David Wieringa <wieringa@xroads.com> wrote:
>
> In a recent code walk-thru at work, someone suggested that different
> compilers process logical OR's differently.
>
> e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
> that x will be evaluated before y or z.
>
> They didn't disagree that if the first (or second) expression evaluated
> to true that the compiler would ignore the remaining expressions.
>
> Can someone solve this disagreement?
>
> According to my C++ book (Bjarne's The C++ Programming Language), it
> states that all but a few operators are left-associative. I take this
> to mean that || is included and that multiple ||'s will be executed from
> left to right.
>
> True? or compiler dependent?
>
> If so, can we assume that the compiler will stop evaluating expressions
> at the first "true" it finds? (since any true of an OR expression
> results in a true result)
>
<Jack>
Whoever made this suggestion doesn't know C or C++ very well. The operation
of the logical AND and OR operators has been defined in its present form since
K&R1. If you want specific quotations from the standard, here is ANSI/ISO/IEC
14882:1998, the new C++ International Standard.
5.14
The && operator groups left-to-right. The operands are both implicitly
converted to type bool. The result is true if both operands are true and
false otherwise. Unlike &, && is guaranteed left-to-right evaluation: the
second operation is not evaluated if the first operand is true.
5.15
The || operator groups left-to-right. The operands are both implicitly
converted to bool. It returns true if either of its operands is true, and
false otherwise. Unlike |, || guarantees left-to-right evaluation; moreover,
the second operand is not evaluated if the first operand evaluates to true.
</Jack>
> BTW, we're using Sun's CC 4.2 C++ compiler.
>
> Any _authoritative_ assistance is greatly appreciated,
>
> Dave
>
> While I'm at it... I was going to post another message for this one,
> but I just realized I should have looked something up at work and I
> forgot. (my books are at work and I don't have access to the usenet at
> work) ...so I'll tag it on this message as an added bonus.
>
> Subject: Copy Constructors use of Assignment Operator
>
> During the same walk-thru it came up that one should not all the
> classes' assignment operator from the copy constructor (i.e. copy
> constructor of *this = sourceObject). Is there any validy to this?
>
> If this is true, why doesn't the compiler catch this? (or do most of
> them?)
>
> Should one in fact duplicate the assignment code in the copy constructor
> if this is what is needed?
>
> Thanks again,
>
> Dave
>
>
>
> [ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain.COM (Siemel Naran)
Date: 1998/12/15 Raw View
On 15 Dec 1998 07:54:16 GMT, David Wieringa <wieringa@xroads.com> wrote:
>e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
>that x will be evaluated before y or z.
If 'x' and 'y' are types for which operator|| is not defined, then
the order is left to right. 'x' evaluated first; if it is #true
then the whole if(...) is true and 'y' and 'z' are not evaluated.
If 'x' is #false, we go on to evaluate 'y'. This is useful for
things like this,
if (ptr && *ptr==3) ; // same as if (ptr) { if (*ptr==3) ; }
If operator|| is overloaded for a class type, then the order of
evaluation is not garuanteed. That is, x||y calls
operator||(x,y);
and the compiler can evaluate 'x' before 'y', 'y' before 'x', or
both at the same time.
As for "x||y||z", it is parsed as
operator||(x||operator||(y,z));
op||
- -
- -
x op||
- -
- -
y z
Author: Larry Brasfield <larry_br@sea_net.com>
Date: 1998/12/15 Raw View
David Wieringa wrote in message <3675FB04.363A624B@xroads.com>...
>
>In a recent code walk-thru at work, someone suggested that different
>compilers process logical OR's differently.
If we commonly had to work with tools that were
that badly broken, we would never have gotten
to the level of progress reached today. I have
never seen a C or C++ compiler that got the
execution of || or && wrong.
>e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
>that x will be evaluated before y or z.
The language guarantees it. Any compiler
that fails to respect that guarantee is garbage.
>They didn't disagree that if the first (or second) expression evaluated
>to true that the compiler would ignore the remaining expressions.
>
>Can someone solve this disagreement?
Yes. Verify that your compiler does the right
thing, then shut up such noise in your review.
If the compiler fails, throw it out.
>According to my C++ book (Bjarne's The C++ Programming Language), it
>states that all but a few operators are left-associative. I take this
>to mean that || is included and that multiple ||'s will be executed from
>left to right.
>
>True? or compiler dependent?
True and guaranteed so.
>If so, can we assume that the compiler will stop evaluating expressions
>at the first "true" it finds? (since any true of an OR expression
>results in a true result)
That's the rule. Has been for decades.
>BTW, we're using Sun's CC 4.2 C++ compiler.
Sun's compiler is not broken like that.
>Any _authoritative_ assistance is greatly appreciated,
This is clearly spelled out. You, too, can buy a
copy of the C++ standard for $18 and see so
for yourself.
>Dave
>
>While I'm at it... I was going to post another message for this one,
>but I just realized I should have looked something up at work and I
>forgot. (my books are at work and I don't have access to the usenet at
>work) ...so I'll tag it on this message as an added bonus.
>
>Subject: Copy Constructors use of Assignment Operator
>
>During the same walk-thru it came up that one should not all the
>classes' assignment operator from the copy constructor (i.e. copy
>constructor of *this = sourceObject). Is there any validy to this?
Yes. A constructor converts raw memory to a
proper object of the class. The assignment
copies a value onto an already constructed
object. This often means freeing the prior
held-by-reference content of the object.
Such freeing for junk found in raw memory
would be a disastor. Learn to distinguish
between assignment and construction
before using C++ for commercial work.
>If this is true, why doesn't the compiler catch this? (or do most of
>them?)
C++ compilers are not such hand-holders,
and I doubt it would be practical to try.
>Should one in fact duplicate the assignment code in the copy constructor
>if this is what is needed?
Probably. Bit-blasting stuff that is known
to be safely memcpy()'able can be shared
between copy and assign, but you have to
be careful. I would not form the habit of
making such tiny, low-level, dangerous
optimizations until learning a lot more.
>Thanks again,
Sure.
--Larry Brasfield
Above opinions may be mine alone.
(Humans may reply at unundered larry_br@sea_net.com )
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1998/12/15 Raw View
David Wieringa wrote:
>
> In a recent code walk-thru at work, someone suggested that different
> compilers process logical OR's differently.
>
> e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
> that x will be evaluated before y or z.
>
> They didn't disagree that if the first (or second) expression evaluated
> to true that the compiler would ignore the remaining expressions.
>
> Can someone solve this disagreement?
>
> According to my C++ book (Bjarne's The C++ Programming Language), it
> states that all but a few operators are left-associative. I take this
> to mean that || is included and that multiple ||'s will be executed from
> left to right.
>
> True? or compiler dependent?
|Section 5.15: Logical OR expression [expr.log.or]
| logical-or-expression:
| logical-and-expression
| logical-or-expression || logical-and-expression
|
|1 The || operator groups left-to-right. ... Unlike |, ||
| guarantees left-to-right evaluation; moreover, the second
| operand is not evaluated if the first operand evaluates to true.
|
|2. ... All side effects of the first expression except for
| destruction of temporaries (12.2) happen before the second
| expression is evaluated.
> If so, can we assume that the compiler will stop evaluating expressions
> at the first "true" it finds? (since any true of an OR expression
> results in a true result)
Yes.
> Subject: Copy Constructors use of Assignment Operator
>
> During the same walk-thru it came up that one should not all the
> classes' assignment operator from the copy constructor (i.e. copy
> constructor of *this = sourceObject). Is there any validy to this?
Yes. Nasty things can happen in derived classes if you do this. Think
about it.
> If this is true, why doesn't the compiler catch this? (or do most of
> them?)
It's not invalid code, it's poor design, and not necessarily a problem
if done right for a class that you do not intend to be derived from.
> Should one in fact duplicate the assignment code in the copy constructor
> if this is what is needed?
It's better to have both the assignment operator and the copy
constructor share the common code by have both call a third member
function.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Martijn Lievaart" <nobody@orion.nl>
Date: 1998/12/15 Raw View
David Wieringa wrote in message <3675FB04.363A624B@xroads.com>...
>
>In a recent code walk-thru at work, someone suggested that different
>compilers process logical OR's differently.
>
>e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
>that x will be evaluated before y or z.
>
>They didn't disagree that if the first (or second) expression evaluated
>to true that the compiler would ignore the remaining expressions.
>
>Can someone solve this disagreement?
It is a special case and it's called short-circuiting. With the logical
operators, the operands are evaluated left to right and whenever the result
is known, the rest of the expression is not evaluated.
Let's take an example:
bool t() { return true; }
bool f() { return false; }
bool x1 = t() || f(); // f() never called
bool x2 = t() && f(); // both called
bool x3 = f() || t(); // both called
bool x4 = f() && t(); // t() never called
Note that this has little to do with precedence.
>
>According to my C++ book (Bjarne's The C++ Programming Language), it
>states that all but a few operators are left-associative. I take this
>to mean that || is included and that multiple ||'s will be executed from
>left to right.
>
Yes, || is left associative but no, that doesn't mean that they are executed
left to right, they are, but that is a result of the special
short-circuiting rule.
Take as an example the following.
int f1();
int f2();
int f3();
int x = f1()-f2()+f3();
Operators + and - are left associative. Does this mean that the operands are
evaluated (executed) left to right? No. You don't know in which order the
functions are called, it is implementation dependent. All you know is that
the result is (f1()-f2())+f3() and not f1()-(f2()+f3()), this is what the
precedence rules establish. The following implementations are all equally
valid and others are possible:
// pseudo code, assembler written as C
t1 = f1();
t2 = f2();
t3 = f3();
x = t1-t2;
x = x + t3;
t3 = f3();
t2 = f2();
t1 = f1();
x = t1-t2;
x = x + t3;
t2 = f2();
t1 = f1();
x = t1-t2;
t3 = f3();
x = x + t3;
>True? or compiler dependent?
>
>If so, can we assume that the compiler will stop evaluating expressions
>at the first "true" it finds? (since any true of an OR expression
>results in a true result)
>
Yes.
>BTW, we're using Sun's CC 4.2 C++ compiler.
>
>Any _authoritative_ assistance is greatly appreciated,
>
I'm not sure I qualify :^> but your welcome.
>Dave
>
>While I'm at it... I was going to post another message for this one,
>but I just realized I should have looked something up at work and I
>forgot. (my books are at work and I don't have access to the usenet at
>work) ...so I'll tag it on this message as an added bonus.
>
>Subject: Copy Constructors use of Assignment Operator
>
>During the same walk-thru it came up that one should not all the
>classes' assignment operator from the copy constructor (i.e. copy
>constructor of *this = sourceObject). Is there any validy to this?
>
This advise is mostly given because they are different for most classes. To
use the assignment operator may lead to subtle errors because you forget to
cleanup something. A probably better approach would be to use a ceanup and a
init routine:
// pseudocode
class X
{
X(const X& x)
{ init(x); }
~X()
{ cleanup(); }
operator=(const X& x)
{ cleanup(); init(x); }
};
But this is not always appropriate as well.
>If this is true, why doesn't the compiler catch this? (or do most of
>them?)
>
Hmmm..... Pass.
>Should one in fact duplicate the assignment code in the copy constructor
>if this is what is needed?
>
Factor out the common code.
>Thanks again,
>
>Dave
>
>
Your welcome.
Martijn
--
My email address is intentionally invalid
reply to mlievaart at orion in nl
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jim.hyslop@leitch.com
Date: 1998/12/15 Raw View
In article <3675FB04.363A624B@xroads.com>,
David Wieringa <wieringa@xroads.com> wrote:
>
> In a recent code walk-thru at work, someone suggested that different
> compilers process logical OR's differently.
>
> e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
> that x will be evaluated before y or z.
The Standard states: "The || operator groups left-to-right. ... Unlike |, ||
guarantees left-to-right evaluation; moreover, the second operand is not
evaluated if the first operand evaluates to true." (Section 5.15).
Therefore, if x is true, neither y nor z will be evaluated - if y or z are
function calls (which is, I suspect, the reason the whole discussion came
about) those functions will not be called.
This is known as "boolean short-circuit evaluation" and can be quite useful at
times, for example:
// p is a pointer to some type
if (p != NULL && p->SomeFunction() < someValue)
The above code is guaranteed never to fail - if p is NULL, then
p->SomeFunction will never get called. I usually highlight any such
dependencies with a comment such as: // Note: boolean short-circuit logic in
effect if (...)
[snip]
> While I'm at it... I was going to post another message for this one,
> but I just realized I should have looked something up at work and I
> forgot. (my books are at work and I don't have access to the usenet at
> work) ...so I'll tag it on this message as an added bonus.
>
> Subject: Copy Constructors use of Assignment Operator
>
> During the same walk-thru it came up that one should not all the
> classes' assignment operator from the copy constructor (i.e. copy
> constructor of *this = sourceObject). Is there any validy to this?
This question may boil down to more of an opinion than hard facts. There are
potential problems with this - certain members (references, for example)
cannot be assigned, they can only be initialized. You must also be sure to
default-initialize your values to a sane state, otherwise if you have (for
example) a pointer, which your op= deletes then reassigns, you'll be in
biiiig trouble. For example:
class T
{
char *c;
public:
T(const T&other) : c(0) {*this=other;}
T&operator=(const T&other)
{
delete c;
c=new char[strlen(other.c)+1];
strcpy(c, other.c);
}
};
In the above case, you must initialize c to a sane value otherwise 'delete c;'
will crash your program.
It really depends on the data types you are storing - if you are storing
types with trivial constructors, then it may not make much of a difference.
If, on the other hand, your members are classes with non-trivial constructors
or copy assignment operators, then it could have a significant performance
impact - you'll be default-initializing everything (this will happen
automatically before the body of the ctor runs) then assigning new values to
everything. If this sounds familiar, it's because it's exactly the same
argument used to encourage using member-initialization lists instead of
assignment within the default ctor body.
--
Jim
Note to recruitment agencies: I delete unsolicited email from
recruitment agencies without reading it, so don't even bother.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Matt Seitz" <mseitz@meridian-data.com>
Date: 1998/12/15 Raw View
David Wieringa wrote in message <3675FB04.363A624B@xroads.com>...
>
>In a recent code walk-thru at work, someone suggested that different
>compilers process logical OR's differently.
>
>e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
>that x will be evaluated before y or z.
>
>They didn't disagree that if the first (or second) expression evaluated
>to true that the compiler would ignore the remaining expressions.
>
>Can someone solve this disagreement?
Dr. Stroustrup writes in section 6.2.2 of THE C++ PROGRAMMING LANGUAGE,
Third Edition,
"The operators , (comma), && (logical and), and || (logical or) guarantee
that their left-hand operand is evaluated before their right-hand operand."
So you are correct, that x will be evaluated before y, and y before z.
However, Dr. Stroustup goes on to say:
"For built-in types, the second operand of && is evaluated only if its first
operand is true, and the second operand of || is evaluated only if its first
operand is false; ...".
I infer from that statement that for user-defined types and functions the
second operand may be evaluated, even if the first operand is false.
So the rules seem to be:
1. x will always be evaluated before y.
2. If x is false, then
2a. if x and y are built-in types, y will not be evaluated
2b. if x or y is not a built-in type, y may be evaluated
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Biju Thomas <bijuthom@ibm.net>
Date: 1998/12/15 Raw View
In article <3675FB04.363A624B@xroads.com>,
David Wieringa <wieringa@xroads.com> wrote:
>
> In a recent code walk-thru at work, someone suggested that different
> compilers process logical OR's differently.
>
> e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
> that x will be evaluated before y or z.
Nonsense. This is something guaranteed even in C. For a recent exposition,
read section 6.2.2 in Stroustrup's C++PL 3rd ed. It is called short-circuit
evaluation.
> During the same walk-thru it came up that one should not all the
> classes' assignment operator from the copy constructor (i.e. copy
> constructor of *this = sourceObject). Is there any validy to this?
Generally it is not advised. Because, in your assignment operator, you will be
assuming that the state of the lhs object will be valid. This is not true in
copy constructors. For example,
class Foo
{
public:
Foo ( const Foo& other);
Foo& operator= ( const Foo& rhs );
private:
Bar* myBar; // owns the 'Bar' object
};
Your assignment operator will be like:
Foo& Foo::operator= ( const Foo& rhs )
{
if ( this != &rhs )
{
delete myBar;
// The above will lead to undefined result if you call it
// on uninitialized variable, which may happen if you do it
// from copy constructor
myBar = NULL;
if ( rhs.myBar )
myBar = new Bar(*rhs.myBar);
}
}
Also, if your assignment operator is virtual (which is generally not
recommended), it won't invoke the proper operator in the copy constructor of a
base class.
> If this is true, why doesn't the compiler catch this? (or do most of
> them?)
>
Well, you can still use that technique if you are sure that it won't create
any problems. So, compilers are not supposed to prevent it.
> Should one in fact duplicate the assignment code in the copy constructor
> if this is what is needed?
If you have similar code in both assignment operator and copy constructor,
factor out the common code and put in a private member function. Simple!
Regards,
Biju Thomas
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sellis@un-geocities.com (Sean Ellis)
Date: 1998/12/15 Raw View
David Wieringa <wieringa@xroads.com> wrote:
>In a recent code walk-thru at work, someone suggested that different
>compilers process logical OR's differently.
>
>e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
>that x will be evaluated before y or z.
> [...]
In "The C++ Programming Language" 2nd edition, section 3.2.2 states:
"The operators
, && ||
guarantee that their left-hand operand is evaluated before their
right-hand operand."
Similarly, the April 1995 version of the draft ANSI standard states:
"5.15 Logical OR operator
1. logical-or-expression:
logical-and-expression
logical-or-expression || logical-and-expression
The || operator groups left-to-right. The operands are both converted
to bool (4.13). It returns true if either of its operands is true, and
false otherwise. Unlike |, || guarantees left-to-right evaluation;
moreover, the second operand is not evaluated if the first operand
evaluates to true.
2 The result is a bool. All side effects of the first expression
except for destruction of temporaries (12.2) happen before the second
expression is evaluated."
...and I don't expect it to have changed since then.
Sean
|||||||| 012345678 Proportiometer(TM)
######## ^ [Non spammers: Delete "un-" after @ in reply-to field]
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1998/12/15 Raw View
In article <3675FB04.363A624B@xroads.com>, wieringa@xroads.com says...
>
> In a recent code walk-thru at work, someone suggested that different
> compilers process logical OR's differently.
>
> e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
> that x will be evaluated before y or z.
If x and y (for example) are types that use an overloaded operator ||,
the order of evaluation is not guaranteed at all -- this means it's
usually a mistake to overload operator || (or &&).
If x, y and z are of built-in types, or can/will be converted to
built-in types, then the compiler has to act like x, y and z were
evaluated from right to left, but the real order of evaluation may be
different. If there are side-effect from the evaluation itself so you
need to ensure that the evaluation is really in the order you want,
then you want to declare the variables volatile.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1998/12/15 Raw View
FB04.363A624B@xroads.com>,
David Wieringa <wieringa@xroads.com> wrote:
>
> In a recent code walk-thru at work, someone suggested that different
> compilers process logical OR's differently.
>
> e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
> that x will be evaluated before y or z.
Strictly speaking, you cannot guarantee anything about the actual order
of execution, as long as the observable behavior is the same.
> They didn't disagree that if the first (or second) expression evaluated
> to true that the compiler would ignore the remaining expressions.
>
> Can someone solve this disagreement?
>
> According to my C++ book (Bjarne's The C++ Programming Language), it
> states that all but a few operators are left-associative. I take this
> to mean that || is included and that multiple ||'s will be executed from
> left to right.
>
> True? or compiler dependent?
There are two different points to consider. The first is logical
grouping -- the operators group from left to right (as does
e.g. addition). This doesn't say anything about the order of execution,
however. The second is the ordering of side effects (observable
behavior). If the expressions have no side effects, the compiler can
order them any way it chooses, evaluate all of them, or some of them
twice, or whatever it wants, as long as the correct branch of the if is
taken.
The ordering of side effects is controlled by sequence points -- if
there are no intervening sequence points, then the order of side effects
is not defined. As it happens, however, || and && are sequence points,
so all side effects of x must have finished before the evaluation of y
starts. Again, of course, with regards to observable behavior -- if the
compiler can determine that y will be evaluated, and that the side
effects of x will not have any effect on its evaluation, then it might
differ the side effects, because there is no way for a conforming
program to tell.
> If so, can we assume that the compiler will stop evaluating expressions
> at the first "true" it finds? (since any true of an OR expression
> results in a true result)
Yes. Formally, the compiler might generate the code differently, but
the observable behavior must be as if it stopped evaluating the
expressions.
> BTW, we're using Sun's CC 4.2 C++ compiler.
>
> Any _authoritative_ assistance is greatly appreciated,
>
> Dave
>
> While I'm at it... I was going to post another message for this one,
> but I just realized I should have looked something up at work and I
> forgot. (my books are at work and I don't have access to the usenet at
> work) ...so I'll tag it on this message as an added bonus.
>
> Subject: Copy Constructors use of Assignment Operator
>
> During the same walk-thru it came up that one should not all the
> classes' assignment operator from the copy constructor (i.e. copy
> constructor of *this = sourceObject). Is there any validy to this?
There may be. On entering the copy constructor, the object isn't
constructed. Calling assignment on an incomplete object may cause
problems. This would typically be the case if the object used dynamic
memory: the assignment operator would start by freeing the memory, and
in the case of the copy constructor, would call delete on an
uninitialized pointer.
> If this is true, why doesn't the compiler catch this? (or do most of
> them?)
>
> Should one in fact duplicate the assignment code in the copy constructor
> if this is what is needed?
Or factor the common code out into a function, yes. Or simply ensure
that the assignment will work, say by first initializing all pointers to
null.
--
James Kanze GABI Software, S rl
Conseils en informatique orient objet --
-- Beratung in industrieller Datenverarbeitung
mailto: kanze@gabi-soft.fr mailto: James.Kanze@dresdner-bank.com
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Paul Grealish <paul.grealish@uk.geopak-tms.com>
Date: 1998/12/15 Raw View
David Wieringa wrote:
>
> In a recent code walk-thru at work, someone suggested that different
> compilers process logical OR's differently.
>
> e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
> that x will be evaluated before y or z.
Short circuit evaluation is guarenteed by the standard
as long as you don't overload operator|| or operator&&
(Meyers, "More Effective C++").
Sorry, I can't quote the relevant portion of the standard.
> (snip)
>
> While I'm at it... I was going to post another message for this one,
> but I just realized I should have looked something up at work and I
> forgot. (my books are at work and I don't have access to the usenet at
> work) ...so I'll tag it on this message as an added bonus.
Best to make a separate post - makes posts and threads
simpler/easier to read and follow.
--
+---------------------------------+
| Paul Grealish |
| GEOPAK-TMS Limited |
| Cambridge, England |
| paul.grealish@uk.geopak-tms.com |
+---------------------------------+
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Ross Smith" <ross.s@ihug.co.nz>
Date: 1998/12/15 Raw View
David Wieringa wrote in message <3675FB04.363A624B@xroads.com>...
>
>In a recent code walk-thru at work, someone suggested that different
>compilers process logical OR's differently.
>
>e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
>that x will be evaluated before y or z.
That would be true for most operators; for example, if you replace ||
with | (bitwise or) in the above expression, there would be no
guarantee about which order x, y, and z would be avaluated in. But the
two logical binary operators, || and &&, are special cases. Unlike all
other operators, their arguments *are* guaranteed to be evaluated
strictly left to right (and if the LHS is enough to determine the
result, the RHS is not evaluated at all).
If different compilers do this differently, they're broken.
--
Ross Smith ................................... mailto:ross.s@ihug.co.nz
.............. The Internet Group, Auckland, New Zealand ..............
* * * * *
To err is human. To really screw up requires the root password.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/12/15 Raw View
In article <3675FB04.363A624B@xroads.com>,
David Wieringa <wieringa@xroads.com> wrote:
>
> In a recent code walk-thru at work, someone suggested that different
> compilers process logical OR's differently.
> e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
> that x will be evaluated before y or z.
> They didn't disagree that if the first (or second) expression evaluated
> to true that the compiler would ignore the remaining expressions.
>
> Can someone solve this disagreement?
>
> According to my C++ book (Bjarne's The C++ Programming Language), it
> states that all but a few operators are left-associative. I take this
> to mean that || is included and that multiple ||'s will be executed from
> left to right.
>
> True? or compiler dependent?
>
> If so, can we assume that the compiler will stop evaluating expressions
> at the first "true" it finds? (since any true of an OR expression
> results in a true result)
>
> BTW, we're using Sun's CC 4.2 C++ compiler.
>
> Any _authoritative_ assistance is greatly appreciated,
>
> Dave
In standard C++, there are two cases.
1. The type of x, y, and z are classes for which you have defined
operator||(). In this case, there will always be two calls to
that function. x and y will be evaluated before the first call,
and z will be evaluated before the second call, but that's all
you can say for sure. It's legal to evaluate y, and then z, and
then x, and then call operator|| twice.
2. The type of x, y, and z are built-in types. In this case, you
are using the built-in operator ||. This operator uses
"short-circuit" evaluation: x will be evaluated first. If it
is true, y and z will never be evaluated. If it is false,
then y is evaluated second -- and if it is true, z is never
evaluated. If x and y are both false then z is examined,
always third of the three.
BTW, the order of association does not directly have any influence
on the order of evaluation. For instance,
a * b + c
Since the result of the multiplication is added to c, you might
think that a and be must be evaluated before c is. But that's
not the case. The compiler might evaluate all three operands in
some order before doing any of the math, if it chose to do so.
And even if Sun's compiler did what you expected today, the next
version of the same compiler might do it differently. In short:
never assume.
> Subject: Copy Constructors use of Assignment Operator
>
> During the same walk-thru it came up that one should not [call] the
> classes' assignment operator from the copy constructor (i.e. copy
> constructor of *this = sourceObject). Is there any validy to this?
It depends on the class. If operator=() can work correctly with
data members that are not already initialized, then there is no
problem.
class myDate {
unsigned long m_date;
public:
myDate() : m_date(0) {}
myDate(const myDate&m) { (*this) = m; }
myDate &operator=(const myDate&m) { m_date = m.m_date; return *this; }
// ...
};
This isn't the way I would do it, but it's perfectly valid. But the
same technique can lead to problems in other classes:
class myArray {
unsigned int m_size;
unsigned int *m_ary;
public:
~myArray() { delete[] m_ary; }
myArray() : m_size(0), m_ary(0) {}
myArray(const myArray&m) { (*this) = m; }
myArray &operator=(const myArray&m);
// ...
};
myArray &myArray::operator=(const myArray&m) {
if (m_ary != m.m_ary) { // Guard against copy to self
delete[] m_ary; // **** OOPS! ****
m_ary = new int[m.m_size];
#if 1
m_size = m.m_size;
memcpy(m_ary, m.m_ary, sizeof(int)*m_size);
#else
for (m_size=0; m_size<m.m_size; ++m_size)
m_ary[m_size]=m.m_ary[m_size];
#endif
}
return *this;
}
You can see what happens when operator= is called from the copy
constructor. The line marked "OOPS" deletes the old array -- but
since the old array pointer was never initialized to 0 (or
anything else), the result is undefined.
> If this is true, why doesn't the compiler catch this? (or do most of
> them?)
Because it's not always a mistake.
> Should one in fact duplicate the assignment code in the copy constructor
> if this is what is needed?
If this is what is needed, then by definition you need this.
Personally, whenever reasonable, I like to do most of the work
in the member-initializers. (You can see this in both of my
examples above. This way is never less efficient than direct
assignment in the constructor body, and sometimes can be much
more efficient -- but there is often reasons that you can't do
it for all member variables). However, a common technique is to
use private functions. You might call one assign and the other
destroy. Then all of the constructors call assign, the
destructor calls destroy, and the assignment operator calls
both destroy and assign.
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/15 Raw View
In article <755dp5$38k@news3.euro.net>, Martijn Lievaart
<nobody@orion.nl> writes
>Yes, || is left associative but no, that doesn't mean that they are executed
>left to right, they are, but that is a result of the special
>short-circuiting rule.
I always knew it as lazy evaluation.
Francis Glassborow Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: source@netcom.com (David Harmon)
Date: 1998/12/15 Raw View
On 15 Dec 1998 07:54:16 GMT, David Wieringa <wieringa@xroads.com> wrote:
>
>In a recent code walk-thru at work, someone suggested that different
>compilers process logical OR's differently.
>
>e.g. In the code "if( x || y || z) { ... }", you can't be guarantee
>that x will be evaluated before y or z.
That depends on what x, y, and z are. If they are ints, or bools, or
get converted to such, then they are evaluated sequentially until one is
true. If x is true, y and z must not be evaluated at all. This is a
very important part of the definition of operator||.
If x, y, and z are all classes with their own operator|| defined, then
operator|| is called as an ordinary function and the special rule above
does not apply. In that case, x, y, and z can be evaluated in _any_
order.
>According to my C++ book (Bjarne's The C++ Programming Language), it
>states that all but a few operators are left-associative. I take this
>to mean that || is included and that multiple ||'s will be executed from
>left to right.
Sorry, that is not what it means. The difference can be rather subtle.
Associativity is strictly about how parts are grouped, and has little to
do with order of evaluation. The expressions:
( x / y ) / z and x / ( y / z )
are different in an associative sort of way, but in either of them x, y,
and z can all be individualy evaluated, in any order, before being
combined.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]