TL;DR
Use any. They are almost the same.
Boring answer
As usual, there are pros and cons.
Use std::reverse_iterator:
- When you are sorting custom types and you don't want to implement
operator>() - When you are too lazy to type
std::greater<int>()
Use std::greater when:
- When you want to have more explicit code
- When you want to avoid using obscure reverse iterators
As for performance, both methods are equally efficient. I tried the following benchmark:
#include <algorithm> #include <chrono> #include <iostream> #include <fstream> #include <vector> using namespace std::chrono; /* 64 Megabytes. */ #define VECTOR_SIZE (((1 << 20) * 64) / sizeof(int)) /* Number of elements to sort. */ #define SORT_SIZE 100000 int main(int argc, char **argv) { std::vector<int> vec; vec.resize(VECTOR_SIZE); /* We generate more data here, so the first SORT_SIZE elements are evicted from the cache. */ std::ifstream urandom("/dev/urandom", std::ios::in | std::ifstream::binary); urandom.read((char*)vec.data(), vec.size() * sizeof(int)); urandom.close(); auto start = steady_clock::now(); #if USE_REVERSE_ITER auto it_rbegin = vec.rend() - SORT_SIZE; std::sort(it_rbegin, vec.rend()); #else auto it_end = vec.begin() + SORT_SIZE; std::sort(vec.begin(), it_end, std::greater<int>()); #endif auto stop = steady_clock::now(); std::cout << "Sorting time: " << duration_cast<microseconds>(stop - start).count() << "us" << std::endl; return 0; }
With this command line:
g++ -g -DUSE_REVERSE_ITER=0 -std=c++11 -O3 main.cpp \ && valgrind --cachegrind-out-file=cachegrind.out --tool=cachegrind ./a.out \ && cg_annotate cachegrind.out g++ -g -DUSE_REVERSE_ITER=1 -std=c++11 -O3 main.cpp \ && valgrind --cachegrind-out-file=cachegrind.out --tool=cachegrind ./a.out \ && cg_annotate cachegrind.out
std::greater demo std::reverse_iterator demo
Timings are same. Valgrind reports the same number of cache misses.
reverse_iterator's.std::sort(b, e);puts the minimum atb(in our caserbegin, so the last element) and the maximum ate(in our caserend, so the first element).