Re: Postfix is slower than postfix: how likely?
Greg Herlihy wrote:
The speed difference between prefix and postfix incrementing an
iterator can readily be measured with, say, a std::vector of
std::string's:
#include <iostream>
#include <vector>
#include <string>
using std::vector;
using std::string;
void Output(std::vector<std::string>::const_iterator iter);
int main()
{
vector<string> v;
v.resize(10000, "abc");
vector<string>::const_iterator iter = v.begin();
do {
Output( ++iter);
} while( iter != v.end());
}
void Output(std::vector<string>::const_iterator iter)
{
std::cout << *iter;
}
The user and system time needed to run this program are:
user 0m0.009s
sys 0m0.007s
It gives me a segmentation fault at the end, because it tries
to dereference the nonexistent element off the end of the array.
But anyway your point is taken.
Replacing the do loop with this while loop:
while (iter != v.end())
{
Output( iter++);
}
takes measurably more time to complete:
user 0m0.016s
sys 0m0.026s
In other words, due to the extra copying required, the
postfix-incrementing iteration is on the order of 2.5 times as slow as
the same iteration performed with a prefix-incrementing iterator. A
difference in time that should not be at all surprising.
Fine, but it's not the case where the return value is ignored (as often
in the third part of a 'for' construct). If postfix can be as fast as
prefix in some cases, that's because copying is optimized away there,
and it would be hard if the return value were actually used.
I have always wished that the language had been defined in such a way
that didn't allow separate overloading of prefix and postfix operators
but allowed users to define "how to increment/decrement" only. Then
compilers could have avoided making copies in postfix operators by
first using the value for evaluation and later invoke the user-defined
operator to actually perform the increment/decrement (somewhat as in C).
Under current rules, where prefix and postfix operators are allowed
(though not recommended) to do completely different things, it's hard
for compilers to do that. And we are advised to write
while (it != end) { foo(*it); ++it; }
instead of
while (it != end) { foo(*it++); }
in general, so the postfix operator became pretty useless. I cannot
think of any cases where the postfix operator is really necessary or
preferred, except this one case:
while (it != end) {
if (pred(*it))
v.erase(it++); // call erase() with the old value of it
// but it should be incremented before that!
else
++it;
}
which is almost equivalent to but much clearer than:
while (it != end) {
if (pred(*it)) {
iterator old(it);
++it;
v.erase(old);
}
else
++it;
}
(which is what std::list<>::erase() essentially does).
--
Seungbeom Kim
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]