std::distance în C++

Iteratori C++98

Numără câte poziții sunt între doi iteratori, adică câte elemente are intervalul [prim, ultim).

Sintaxă
template<class InputIt>
typename std::iterator_traits<InputIt>::difference_type distance(InputIt prim, InputIt ultim);

Ce face std::distance

std::distance(prim, ultim) returnează numărul de pași de la prim la ultim. Cel mai des este folosit pentru a afla poziția (indicele) unui element găsit: std::distance(v.begin(), it).

Pentru vectori și alte containere cu acces direct, calculul este imediat (ultim - prim) și rezultatul poate fi negativ dacă ultim este înaintea lui prim. Pentru liste, seturi și map-uri, funcția parcurge intervalul pas cu pas, iar ultim trebuie să poată fi atins din prim.

Parametri

Parametru Descriere
prim, ultim Doi iteratori din același container.

Ce returnează

Numărul de elemente dintre ei, ca număr cu semn (std::ptrdiff_t pentru majoritatea containerelor).

Exemple

Exemplul 1: Poziția unui element găsit

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

int main() {
    std::vector<std::string> orase{"Arad", "Brașov", "Cluj", "Iași"};
    auto it = std::find(orase.begin(), orase.end(), "Cluj");
    std::println("Cluj este pe poziția {}", std::distance(orase.begin(), it));

    std::list<int> l{3, 6, 9, 12, 15};
    auto prag = std::find_if(l.begin(), l.end(), [](int x) { return x > 8; });
    std::println("{} elemente sunt cel mult 8, {} sunt mai mari", std::distance(l.begin(), prag), std::distance(prag, l.end()));
}

Rezultat

Cluj este pe poziția 2
2 elemente sunt cel mult 8, 3 sunt mai mari

Greșeli frecvente

  • Apelezi std::distance(prim, ultim) pe o listă cu ultim înaintea lui prim: funcția merge înainte și nu îl atinge niciodată (comportament nedefinit).
  • Calculezi des std::distance(l.begin(), l.end()) pe o listă mare. Este O(n); l.size() este O(1).

Comenzi înrudite

  • std::advance: Mută un iterator cu n poziții înainte (sau înapoi, pentru n negativ), pentru orice tip de container.
  • std::next: std::next returnează un iterator mutat cu n poziții înainte, std::prev unul mutat înapoi; originalul rămâne neschimbat.
  • std::find: Caută prima apariție a unei valori într-un interval și returnează un iterator către ea.
  • std::vector::begin: begin() dă un iterator la primul element, end() unul după ultimul, iar rbegin() pornește parcurgerea de la coadă.