views:

395

answers:

6

Hi, I'm using std::map to store a lot of elements (pairs of elements) and I have a "little" doubt, what is more efficient to iterate all elements over my std::map, iterator or reverse_iterator?

Thank's.

Salu2.

+11  A: 

Does it really matter? these are the types of the micro optimizations you must try to avoid IMHO. Also, even if the iteration time changes for very large number of elements in the map, the fact that you are trying to iterate through all the elements of such a big map means that most probably you have chosen a wrong data structure.

Naveen
Well, you're right.I wanted to print all elements with the operator "<<" to my class, but if print all std::map, time consuming is excessive. better not do it.Thank you
Miguel Angel
+2  A: 

Unless you have profiled your code and found there to be a significant difference, I just wouldn't be concerned about it.

"Premature optimization is the root of all evil." - Donald Knuth

McWafflestix
+1  A: 

There will likely be no difference. std::reverse_iterator is just a template shim that translates ++'s to --'s at compile time.

For a vector or other contiguous storage container, a forward iterator might interact very slightly better with the cache than a reverse iterator would (unlikely you'd be able to detect it), but for a tree-based container it won't make any difference at all--there won't be any locality of reference to exploit.

Drew Hall
Not true, it's not just a template shim. FYI set/map reverse_iterators are 2x to 3x slower than forward iterators.
vladr
A: 

Me think it does not make sense to use a reverse_iterator; it's counter intuitive.

It would make the code harder to understand, someone will look at the code and go "wtf"; and if you need to put a comment to explain why, it probably means it's not good code to start with.

Max
A: 

I am wondering the need for iteration. Map holds the key-value pairs and normally you use it for the lookup. If you still need to iterate the map for some reasons ( may be deleting pointers contained inside the map etc) then you can use std::for_each. Forget the micro optimizations and you can try to increase the code readability.

aJ
any specific reason for down vote?
aJ
A: 

For the record, dereferencing reverse_iterator on std::map and std::set containers is twice as slow as using iterator -- with both -O3 gcc 3.4.6 and MSVC on Intel/AMD processors (almost 3x as slow on PPC architectures.) Same holds for const_reverse_iterator vs. const_iterator. This is due to the fact that reverse_iterator actually points to the tree node immediately following the tree node to be dereferenced, hence the extra work. std::vector iterators exhibit a much milder difference (reverse_iterator is only ~30% slower on PPC, virtually indistinguishable on Intel/AMD.) Incidentally, a std::vector iterator is about 20x faster than a std::map or std::set iterator.

#include <set>
#include <vector>
#include <stdio.h>
#ifdef _WIN32
#include <sys/timeb.h>
#else
#include <sys/time.h>
#endif
#include <time.h>

#define CONTAINER std::set< int >

double
mygettime(void) {
# ifdef _WIN32
  struct _timeb tb;
  _ftime(&tb);
  return (double)tb.time + (0.001 * (double)tb.millitm);
# else
  struct timeval tv;
  if(gettimeofday(&tv, 0) < 0) {
    perror("oops");
  }
  return (double)tv.tv_sec + (0.000001 * (double)tv.tv_usec);
# endif
}


int main() {
  int i, x = 0;
  CONTAINER bla;
  for (i = 0; i < 10000; bla.insert(bla.end(), i++)) ;

  double t1 = mygettime();

  for (i = 0; i < 100; ++i) {
    for (CONTAINER::iterator it = bla.begin(); it != bla.end(); ++it) {
      x ^= *it;
    }
  }

  printf("forward: %f\n", mygettime() - t1);

  double t2 = mygettime();

  for (i = 0; i < 100; ++i) {
    for (CONTAINER::reverse_iterator it = bla.rbegin(); it != bla.rend(); ++it) {
      x ^= *it;
    }
  }

  printf("reverse: %f\n", mygettime() - t2);

  return 0;
}

Cheers, V.

vladr