I have a function that takes a list of characters and generates the following lexicographic permutation. For fun, I tried to generalize the code for using iterators, as well as the ability to generate permutations of more different types.
template<typename ITER> bool nextPermutation(ITER start, ITER end, std::random_access_iterator_tag) { for(ITER i = end-1; i != start; --i) { if(*(i-1) < *i) { // found where can be swapped for(ITER j = end-1; j != (i-1); --j) { if(*(i-1) < *j) { // found what to swap with auto temp = *j; *j = *(i-1); *(i-1) = temp; // put everything from i on into "sorted" order by reversing for(ITER k = end-1; k > i; --k,++i) { temp = *k; *k = *i; *i = temp; } return true; } } } } return false; }
However, I run into problems when, when I do not use raw pointers, code performance is much slower. Here is my test setup:
template<typename ITER> bool nextPermutation(ITER start, ITER end, std::random_access_iterator_tag); template<typename ITER> bool nextPermutation(ITER start, ITER end) { return nextPermutation(start, end, std::iterator_traits<ITER>::iterator_category()); } #define USE_VECTOR int main(void) { bool hasNext = true; #ifdef USE_VECTOR std::vector<char> c; for(char i = '0'; i <= '9'; ++i) { c.push_back(i); } for(size_t i = 0; i < 999999 && hasNext; ++i) { hasNext = nextPermutation(c.begin(), c.end()); } #else char c[] = "0123456789"; size_t LENGTH = 10; for(size_t i = 0; i < 999999 && hasNext; ++i) { hasNext = nextPermutation(c, c+LENGTH); } #endif std::cout << "done" << std::endl; std::cin.ignore(); return 0; }
When USE_VECTOR defined, it takes ~ 20 seconds to run this test setup. When I determine this, the codes work in less than a second (I did not write a synchronization code, but suffice it to say that there is a very significant difference in performance).
Now my question is, where do I take such a huge performance hit that will affect the use of an iterator (std :: string iterator, std :: vector iterator, etc.) compared to a raw pointer?
source share