std::reverse_iterator în C++

Iteratori C++98

Adaptor care inversează direcția unui iterator: ++ merge spre începutul containerului. Este tipul returnat de rbegin().

Sintaxă
#include <iterator>

std::reverse_iterator<It> r(it);
auto r = std::make_reverse_iterator(it);   // C++14
It base() const;

Ce face std::reverse_iterator

Un std::reverse_iterator învelește un iterator bidirecțional și inversează sensul: ++ merge înapoi, -- înainte. v.rbegin() și v.rend() returnează astfel de iteratori, iar orice algoritm care primește un interval poate lucra de la coadă la început.

Detaliu important: un iterator invers construit din it indică elementul dinaintea lui it. r.base() returnează iteratorul normal de bază, aflat cu o poziție mai la dreapta decât elementul pe care îl citește *r. De aceea, pentru a șterge elementul găsit cu un iterator invers, scrii v.erase(std::next(r).base()).

Parametri

Parametru Descriere
it Iteratorul normal din care se construiește cel invers.

Ce returnează

Un iterator invers; base() returnează iteratorul normal de bază.

Exemple

Exemplul 1: Ultima apariție a unei valori

std::find pe iteratori inverși găsește ultima apariție. base() indică elementul de după, de aceea scădem 1 pentru poziție.

#include <algorithm>
#include <iterator>
#include <print>
#include <vector>

int main() {
    std::vector<int> v{4, 7, 2, 7, 9, 1};
    auto r = std::find(v.rbegin(), v.rend(), 7);
    if (r != v.rend()) {
        auto pozitie = std::distance(v.begin(), r.base()) - 1;
        std::println("Ultimul 7 este pe poziția {}", pozitie);
        std::println("*r = {}, *r.base() = {}", *r, *r.base());
    }
}

Rezultat

Ultimul 7 este pe poziția 3
*r = 7, *r.base() = 9

Exemplul 2: make_reverse_iterator pe un tablou C

#include <iterator>
#include <print>

int main() {
    int numere[] = {1, 2, 3, 4, 5};
    auto inceput = std::make_reverse_iterator(std::end(numere));
    auto sfarsit = std::make_reverse_iterator(std::begin(numere));
    for (auto it = inceput; it != sfarsit; ++it) {
        std::print("{} ", *it);
    }
    std::println();
}

Rezultat

5 4 3 2 1

Greșeli frecvente

  • Folosești r.base() ca și cum ar indica același element ca r. Indică elementul următor; pentru elementul lui r, folosește std::prev(r.base()).
  • Încerci un iterator invers pe std::forward_list: nu se poate, pentru că iteratorii ei merg doar înainte.

Comenzi înrudite

  • std::vector::begin: begin() dă un iterator la primul element, end() unul după ultimul, iar rbegin() pornește parcurgerea de la coadă.
  • std::begin: Funcții libere care dau iteratorul de început și de sfârșit pentru orice container, inclusiv pentru tablourile C.
  • std::next: std::next returnează un iterator mutat cu n poziții înainte, std::prev unul mutat înapoi; originalul rămâne neschimbat.
  • std::reverse: Inversează pe loc ordinea elementelor dintr-un interval.