Topic: Proposal: operator++(int)
Author: Martin Bonner <mbonner@pires.co.uk>
Date: 1996/12/06 Raw View
In article: <586i75$370@toralf.uib.no> boukanov@gluon.fi.uib.no (Igor Boukanov) writes:
>
> Andrew C. Bell (abell@atl.mindspring.com) wrote:
> > Since this is inline, unless you need the result of the operation, a
> > decent optimizing compiler will optimize away the copy construction
> > and return costs anyway.
>
> Compiler can do this only if a source of the copy constructor and all
> functions that it calls available and the ctor do not have any side
> effects.
>
I believe there is specific permission for compilers to optimize away
copy constructions **even if they have side-effects**.
(A conforming program can detect if this optimization has been done or
not).
--
Martin Bonner
Pi Technology, Milton Hall, Church Lane, Milton, Cambridge, ENGLAND
+44 1223 203894
mbonner@pires.co.uk
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: abell@atl.mindspring.com (Andrew C. Bell)
Date: 1996/12/07 Raw View
Martin Bonner <mbonner@pires.co.uk> wrote:
>I believe there is specific permission for compilers to optimize away
>copy constructions **even if they have side-effects**.
Yep; check out 12.8.15 of the April '95 working paper, somewhere
around:
http://www.cygnus.com/misc/wp/draft/special.html#class.copy
"Whenever a class object is copied and the implementation can
prove that either the original or the copy will never again be
used, an implementation is permitted to treat the original and the
copy as two different ways of referring to the same object and not
perform a copy at all. In that case, the object is destroyed at
the later of times when the original and the copy would have been
destroyed without the optimization."
Of course, just because an implementation is allowed to do this, it
doesn't mean it will.
Andrew Bell
abell@mindspring.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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: hickeyr@ibm.net (Rich Hickey)
Date: 1996/12/08 Raw View
Chelly Green <chelly@eden.com> wrote:
>In time-critical code, there are lots of things that you don't want to
>use. But time-critical code is not the norm.
>> because it is always better
>> to write
>>
>> A a;
>> 1.) some_expression(a); ++a;
>>
>> than
>>
>> 2.) some_expression(a++);
>>
>> if more than one expression is allowed.
>> Otherwise ( return a++, if(a++),throw, while, ...)
>> it is generated like the usual hand-crafted operator.
>> That means, the compiler-generated operator depends on the context, where
>> it is used. Dont argue, everybody is allowed to write 1.) instead of 2.).
>> Many people like the short Syntax of 2.). Look at the HP-STL, the
>> programmers there make heavy use of the postfix-operator, even in
>> time-critical function (e.g. copy ). For that reason I do not use
>> some functions of that library.
>But for most programs, the running time isn't determined by the speed of
>STL's copy() from every invocation! It is often determined by a few
>bottleneck routines, or by I/O speed. Most of the time, the performance
>of a piece of code doesn't matter much, so you code for
>readability/robustness/memory usage. When you find a performance
>problem, you tune the code. Algorithms make much more of a difference
>than code tweaking.
>> ( BTW, are there better implementations of the STL available? )
>> The temporary of the usual code cannot be optimized away because 1.)
>> and 2.) have slightly different semantics. The change in the language
>> rules is necessary practical use of operator++(int).
>Perception versus reality. The perceived cost of postfix operator ++ is
>probably higher than the actual cost. The way to find which is the case
>is to use a code performance profiler.
The bottom line, however, is that given that STL encourages delivery
of algorithms sans context, the use of postfix ++ in such algorithms
should be frowned upon, since there are clear-cut cases where the
performance difference is significant (i.e. several times slower).
Consider an iterator adapter that calls new to clone the thing it is
adapting. Even when such an iterator is optimally written, with
reference counting and copy-on-write, postfix ++ forces the creation
of a copy with differing state, and thus the (expensive) allocation of
that resource.
Rich
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: tkunert@rcs7.urz.tu-dresden.de (Thomas Kunert)
Date: 1996/12/01 Raw View
I hate the postfix-operator, because it is too slow.
It is (almost) always defined in that way:
class A {
public:
A operator++(int){
A tmp=*this; ++(*this); return tmp;
}
};
In time-critical code you cannot use it, because it is always better
to write
A a;
1.) some_expression(a); ++a;
than
2.) some_expression(a++);
if more than one expression is allowed.
My proposal:
For classes without operator++(int) the compiler generates it.
The compiler-generated operator should behave like 1.), if it is possible.
Otherwise ( return a++, if(a++),throw, while, ...)
it is generated like the usual hand-crafted operator.
That means, the compiler-generated operator depends on the context, where
it is used. Dont argue, everybody is allowed to write 1.) instead of 2.).
Many people like the short Syntax of 2.). Look at the HP-STL, the
programmers there make heavy use of the postfix-operator, even in
time-critical function (e.g. copy ). For that reason I do not use
some functions of that library. ( BTW, are there better implementations
of the STL available? )
The temporary of the usual code cannot be optimized away because 1.)
and 2.) have slightly different semantics. The change in the language
rules is necessary practical use of operator++(int).
Thomas Kunert
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Chelly Green <chelly@eden.com>
Date: 1996/12/02 Raw View
Thomas Kunert wrote:
>
> I hate the postfix-operator, because it is too slow.
Depends on the use. On built-in types, a decent compiler will compile
'++i;' and 'i++;' to the same machine code. For user-defined types,
postfix operator ++ often returns void, to avoid this overhead.
> It is (almost) always defined in that way:
>
> class A {
> public:
> A operator++(int){
> A tmp=*this; ++(*this); return tmp;
> }
> };
>
> In time-critical code you cannot use it,
In time-critical code, there are lots of things that you don't want to
use. But time-critical code is not the norm.
> because it is always better
> to write
>
> A a;
> 1.) some_expression(a); ++a;
>
> than
>
> 2.) some_expression(a++);
>
> if more than one expression is allowed.
Speed-wise and readability wise. I don't like expressions with
side-effects, unless it's a pointer increment before/after a read, like
'*p++ = 1234'.
> My proposal:
> For classes without operator++(int) the compiler generates it.
> The compiler-generated operator should behave like 1.), if it is possible.
This sounds reasonable, but does it buy much? Hmmm, couldn't you achieve
this by using a proxy object?
// uncomment if compiler doesn't support mutable
//#define mutable
template<class T>
class postfix_inc_proxy : public T {
T* mutable obj;
public:
postfix_inc_proxy( T* t ) : T( *t ), obj( t ) { }
postfix_inc_proxy( postfix_inc_proxy const& rhs ) : obj( rhs.obj )
{ const_cast<postfix_inc_proxy&> (rhs).obj = 0; }
~postfix_inc_proxy() { if ( obj ) ++*obj; }
};
class Int {
int i;
public:
Int( int ii ) : i( ii ) { }
operator int () const { return i; }
Int& operator ++ () { ++i; return *this; }
postfix_inc_proxy<Int> const operator ++ (int) { return this; }
};
#include <iostream.h>
#include <assert.h>
int main()
{
Int i( 10 );
assert( i == 10 );
assert( i++ + i++ == 20 )
// postfix increments happen here
;
assert( i == 12 );
return 0;
}
Not sure how much more efficient (if at all) this would be than a normal
postfix operator ++ definition, though :-)
> Otherwise ( return a++, if(a++),throw, while, ...)
> it is generated like the usual hand-crafted operator.
> That means, the compiler-generated operator depends on the context, where
> it is used. Dont argue, everybody is allowed to write 1.) instead of 2.).
> Many people like the short Syntax of 2.). Look at the HP-STL, the
> programmers there make heavy use of the postfix-operator, even in
> time-critical function (e.g. copy ). For that reason I do not use
> some functions of that library.
But for most programs, the running time isn't determined by the speed of
STL's copy() from every invocation! It is often determined by a few
bottleneck routines, or by I/O speed. Most of the time, the performance
of a piece of code doesn't matter much, so you code for
readability/robustness/memory usage. When you find a performance
problem, you tune the code. Algorithms make much more of a difference
than code tweaking.
> ( BTW, are there better implementations of the STL available? )
> The temporary of the usual code cannot be optimized away because 1.)
> and 2.) have slightly different semantics. The change in the language
> rules is necessary practical use of operator++(int).
Perception versus reality. The perceived cost of postfix operator ++ is
probably higher than the actual cost. The way to find which is the case
is to use a code performance profiler.
--
Chelly Green | chelly@eden.com | C++ - http://www.eden.com/~chelly
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: abell@atl.mindspring.com (Andrew C. Bell)
Date: 1996/12/04 Raw View
tkunert@rcs7.urz.tu-dresden.de (Thomas Kunert) wrote:
>I hate the postfix-operator, because it is too slow.
>It is (almost) always defined in that way:
>class A {
>public:
> A operator++(int){
> A tmp=*this; ++(*this); return tmp;
> }
>};
Since this is inline, unless you need the result of the operation, a
decent optimizing compiler will optimize away the copy construction
and return costs anyway. Most of the time, user-defined increment
operators are inline functions. Moreover, most incrementable classes
are pretty simple, so the copy is simple; and even if the return value
is used, it may only really need a part of class A, and thus the
compiler is free to optimize away all but the copying of the part that
is needed as long as it passes the "as if" rule.
And are you really working on something where a trivial decrease in
execution time is that important? How many of these increments are
you really doing, and is the rest of your code really doing so little
that the performance of this matters? Too many programmers are too
obsessed with getting the absolute best performance, when the users of
their code will never notice the effect of the optimizations anyway.
Andrew Bell
abell@mindspring.com
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: boukanov@gluon.fi.uib.no (Igor Boukanov)
Date: 1996/12/05 Raw View
Andrew C. Bell (abell@atl.mindspring.com) wrote:
> Since this is inline, unless you need the result of the operation, a
> decent optimizing compiler will optimize away the copy construction
> and return costs anyway.
Compiler can do this only if a source of the copy constructor and all
functions that it calls available and the ctor do not have any side
effects.
--
Regards, Igor Boukanov.
igor.boukanov@fi.uib.no
http://www.fi.uib.no/~boukanov/
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Chelly Green <chelly@eden.com>
Date: 1996/12/05 Raw View
Andrew C. Bell wrote:
>
...
> And are you really working on something where a trivial decrease in
> execution time is that important? How many of these increments are
> you really doing, and is the rest of your code really doing so little
> that the performance of this matters?
I think the best way is to run a performance profiler that is the
asychronous sampling type, so you can see *where* in the function the
time is being spent. You can try replacing use of classes with
hand-written code, and see how the performance is affected.
> Too many programmers are too
> obsessed with getting the absolute best performance, when the users of
> their code will never notice the effect of the optimizations anyway.
The users?!? Heck, the programmers too! Well, except for the one who
made the change, since they will have this mental perception of it
actually running faster :-) Taking this further, that's one reason why
we use C++, for (perceived) efficiency. But if performance is often
based on small pieces of code, what about the rest of the code?
Dangerous thoughts...
Perception versus reality. Perception everyone has, while reality is an
indirect conclusion based on perception. Know the limitations of this.
--
Chelly Green | chelly@eden.com | C++ - http://www.eden.com/~chelly
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]