"the c++ standard library, tutorial and reference" book, it says:
++i is faster than i++. the latter involves a temporary object because
it must return the old value/object of i. for this reason, it's
generally better to use ++i.
but, I think, even ++i still has to return a temporary object that is
with new value inside. So, both i++ and ++i have to return a temporary
object. Then, what's the speed difference between i++ and ++i.
This is an abomination, uh, I mean to say class, I created that demonstrates
the difference rather well. Notice that in the postfix case I have to
check to see if there is a temporary object, create it if it doesn't exist,
and assign to it if it does exits. In the prefix form, there is no need to
deal with the temporary object, so there are fewer instructions executed
per call.
I didn't see an obvious way of moving the creation of the temporary object
into constructor since that would lead to unbounded recursion. I could
probably be done by passing some kind of flag to a special constructor.
That might marginally improve performance, but will not make the postfix
form as efficient as the prefix form. Also be aware that I have not tested
the version presented here in so much as it derives from the
util::Referenced baseclass. Additionally, I am less than fully comfortable
with the choice of wrapping the index at the bounds. It does not follow
STL semantics for iterators, and adds a bit of overhead with the '%'
operations.
/***************************************************************************
* Copyright (C) 2005 by Steven T. Hatton *
* (e-mail address removed) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef MATH_BOUNDEDINDEX_H
#define MATH_BOUNDEDINDEX_H
#include <util/Referenced.h>
namespace math {
/*!\brief The BoundedIndex class provides an \c unsigned \c int in the
range \e [0,supremum)
BoundedIndex represents an \c unsigned \c int ragning from \c 0 \e
inclusive
to \c supremum \e exclusive. It provides both C-style increment and
decrement operators (++,--)
as well as Java-style iterator functions (next(), hasNext()) with
bidirectional functionality.
When the value is incremented beyond either bound, it wraps to the
opposing end of the range.
*/
class BoundedIndex: public util::Referenced {
public:
/*!
Constructor creates 0 range index. Intended to support collection
construction;
*/
BoundedIndex()
:_index(0)
,_sup(0)
,_tmp_ptr(0)
{}
/*!
Constructor
The index value is initialized to 0.
\param sup_ value of \c supremum \e exclusive.
*/
explicit BoundedIndex(unsigned sup_)
:_index(0)
,_sup(sup_)
,_tmp_ptr(0)
{}
/*!
Copy Constructor copies both \c index and \c supremum.
*/
BoundedIndex(const BoundedIndex& b)
:_index(b._index)
,_sup(b._sup)
,_tmp_ptr(0)
{}
/*!
Assignment Operator copies both \c index and \c supremum.
*/
BoundedIndex& operator=(const BoundedIndex& b) {
if(b == *this) return *this;
_sup = b._sup;
_index = b._index;
_tmp_ptr = 0;
}
/*!
Assignment operator clamps \c index to \e [0,supremum)
\param index_ The new index value before clamping.
*/
BoundedIndex& operator=(const unsigned& index_) {
_index = index_ % _sup;
return *this;
}
/*!
Conversion operator converts to \c unsigned \c int.
*/
operator unsigned () const { return _index; }
/*!
Prefix increment operator
*/
BoundedIndex& operator++() {
_index = (_index + 1) % _sup;
return *this;
}
/*!
Postfix increment operator
*/
const BoundedIndex& operator++(int) {
if(!_tmp_ptr) _tmp_ptr = new BoundedIndex(*this); else
_tmp_ptr->_index = _index;
_index = (_index + 1) % _sup;
return *_tmp_ptr;
}
/*!
Prefix decrement operator
*/
const BoundedIndex& operator--() {
_index = _index < 1 ? _sup - 1: _index - 1;
return *this;
}
/*!
Postfix decrement operator
\return reference to a temporary copy of this.
*/
BoundedIndex& operator--(int) {
if(!_tmp_ptr) _tmp_ptr = new BoundedIndex(*this); else
_tmp_ptr->_index = _index;
_index = (_index + 1) % _sup;
return *_tmp_ptr;
}
/*!
Compund assignment addition operator.
\return reference to this.
*/
BoundedIndex& operator+=(const unsigned& di_) {
_index = (_index + di_)%_sup;
return *this;
}
/*!
Compund assignment subtraction operator.
\return reference to this.
*/
BoundedIndex& operator-=(const unsigned& di_) {
_index = _index >= di_? (_index - di_): _sup - (di_ - _index)%_sup;
return *this;
}
/*!
Accessor
\return value of \c supremum
*/
unsigned sup() const { return _sup; }
/*!
Mutator
\param sup_ set the value of \c supremum.
*/
void sup(unsigned sup_ ) { _sup = sup_; }
/*!
Accessor
\return value of \c index
*/
unsigned index() const { return _index; }
/*!
Mutator
\param index_ set the value of \c index.
*/
void index(unsigned index_ ) { _index = index_; }
/*!
Tests whether the index can be increased;
*/
bool hasNext() const { return _index < _sup - 1; }
/*!
Tests whether the index can be decreased;
*/
bool hasPrevious() const { return _index > 0; }
/*!
Wrapper for operator++();
*/
BoundedIndex& next() { return operator++(); }
/*!
Wrapper for operator--();
*/
BoundedIndex& previous() { return operator--(); }
protected:
/*!
Destructor.
*/
~BoundedIndex() { delete _tmp_ptr; }
private:
unsigned _index;
unsigned _sup;
BoundedIndex* _tmp_ptr;
};
/*!
BoundedIndex binary addition operator;
*/
BoundedIndex operator+(const BoundedIndex& arg1, const BoundedIndex& arg2)
{
BoundedIndex ret(arg1);
return ret += arg2;
}
/*!
BoundedIndex binary subtraction operator;
*/
BoundedIndex operator-(const BoundedIndex& arg1, const BoundedIndex& arg2)
{
BoundedIndex ret(arg1);
return ret -= arg2;
}
}
#endif