TL; DR
Sử dụng bất kỳ. Chúng gần như giống nhau.
Chán câu trả lời
Như thường lệ, có những ưu và nhược điểm.
Sử dụng std::reverse_iterator
:
- Khi bạn sắp xếp các loại tùy chỉnh và bạn không muốn thực hiện
operator>()
- Khi bạn quá lười để gõ
std::greater<int>()
Sử dụng std::greater
khi:
- Khi bạn muốn có nhiều mã rõ ràng hơn
- Khi bạn muốn tránh sử dụng các trình vòng lặp ngược tối nghĩa
Đối với hiệu suất, cả hai phương pháp đều hiệu quả như nhau. Tôi đã thử điểm chuẩn sau:
#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;
}
Với dòng lệnh này:
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
Thời gian là như nhau. Valgrind báo cáo cùng một số lỗi bộ nhớ cache.