C++11 giới thiệu range-based for loop, nhưng không có sẵn phiên bản ngược. Có thể dùng Boost.Range với boost::adaptors::reverse để duyệt container ngược.
Yêu cầu
- Cài đặt Boost library
- Include
<boost/range/adaptor/reversed.hpp>
Ví dụ với std::list
#include <list>
#include <iostream>
#include <boost/range/adaptor/reversed.hpp>
using namespace std;
int main() {
std::list<int> x {11, 44, 77, 55, 44, 22, 33, 30, 88, 99, 55, 44};
cout << "Vong lap thuan:" << endl;
for (auto i : x) {
cout << i << '\n';
}
cout << "\nVong lap nguoc (Boost):" << endl;
for (auto i : boost::adaptors::reverse(x)) {
cout << i << '\n';
}
}
Kết quả
Vong lap thuan: 11 44 77 55 44 22 33 30 88 99 55 44 Vong lap nguoc (Boost): 44 55 99 88 30 33 22 44 55 77 44 11
Cách hoạt động
boost::adaptors::reverse trả về một adaptor (wrapper) cung cấp begin() và end() ngược lại của container gốc. Range-based for loop dùng các iterator này.
Phương án thay thế không cần Boost (C++11 thuần)
1. Dùng index (cho container có random access)
vector<int> v = {1, 2, 3, 4, 5};
for (size_t i = v.size(); i-- > 0; ) {
cout << v[i] << " ";
}
2. Dùng reverse_iterator
for (auto it = v.rbegin(); it != v.rend(); ++it) {
cout << *it << " ";
}
3. Tự viết adaptor đơn giản (C++11)
template <typename C>
struct Reversed {
C& c;
auto begin() const { return c.rbegin(); }
auto end() const { return c.rend(); }
};
template <typename C>
Reversed<C> reversed(C& c) { return {c}; }
// Sử dụng:
for (auto x : reversed(v)) { cout << x << " "; }
C++20: std::views::reverse
#include <ranges>
#include <vector>
#include <iostream>
int main() {
vector<int> v = {1, 2, 3, 4, 5};
for (int x : v | std::views::reverse) {
cout << x << " ";
}
}
So sánh
| Phương pháp | Yêu cầu | Hỗ trợ container | Độ phức tạp |
|---|---|---|---|
| Boost::adaptors::reverse | Boost | Tất cả (bidirectional) | O(1) setup |
| reverse_iterator | STL | Tất cả | O(1) |
| Index loop | STL | Random access | O(1) |
| C++20 views::reverse | C++20 | Tất cả (bidirectional) | O(1) |
Khuyến nghị
- Đã có Boost: Dùng
boost::adaptors::reverse - Chỉ STL: Dùng
rbegin()/rend()hoặc tự viết adaptor - C++20: Dùng
std::views::reverse(chuẩn, không phụ thuộc Boost)