iterator vs reverse_iterator

前端 未结 6 1566
暗喜
暗喜 2021-01-05 05:52

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

相关标签:
6条回答
  • 2021-01-05 06:08

    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;
    }
    
    0 讨论(0)
  • 2021-01-05 06:11

    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.

    0 讨论(0)
  • 2021-01-05 06:12

    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.

    0 讨论(0)
  • 2021-01-05 06:18

    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.

    0 讨论(0)
  • 2021-01-05 06:21

    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

    0 讨论(0)
  • 2021-01-05 06:24

    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.

    0 讨论(0)
提交回复
热议问题