std::back_inserter în C++

Iteratori C++98

Iteratori de inserare: fiecare scriere prin back_inserter face push_back, iar prin inserter face insert la o poziție.

Sintaxă
template<class Container>
std::back_insert_iterator<Container> back_inserter(Container& c);

template<class Container>
std::insert_iterator<Container> inserter(Container& c, typename Container::iterator poz);

Ce face std::back_inserter

Algoritmii ca std::copy sau std::transform scriu rezultatul printr-un iterator de destinație și presupun că acolo există deja loc. Dacă destinația este un vector gol, scrierea normală ar ieși din vector. std::back_inserter(v) rezolvă problema: fiecare atribuire prin el devine v.push_back(valoare), deci vectorul crește cât e nevoie.

std::inserter(c, poz) face c.insert(poz, valoare) la fiecare scriere. Este varianta potrivită pentru std::set și std::map, care nu au push_back. Există și std::front_inserter, care face push_front (pentru deque și list).

Parametri

Parametru Descriere
c Containerul în care se adaugă.
poz Pentru inserter: poziția la care se inserează (la set, de obicei s.end(); ordinea este oricum cea sortată).

Ce returnează

Un iterator de inserare, dat ca destinație unui algoritm.

Exemple

Exemplul 1: Copiere într-un vector gol

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

int main() {
    std::vector<int> note{4, 9, 7, 3, 10, 6};
    std::vector<int> promovate;                  // gol
    std::copy_if(note.begin(), note.end(), std::back_inserter(promovate), [](int n) { return n >= 5; });
    std::println("Promovate: {}", promovate);

    std::vector<double> procente;
    std::transform(note.begin(), note.end(), std::back_inserter(procente), [](int n) { return n * 10.0; });
    std::println("Procente: {}", procente);
}

Rezultat

Promovate: [9, 7, 10, 6]
Procente: [40, 90, 70, 30, 100, 60]

Exemplul 2: inserter pentru un set

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

int main() {
    std::vector<std::string> comenzi{"Iași", "Cluj", "Iași", "Arad", "Cluj"};
    std::set<std::string> orase;
    std::copy(comenzi.begin(), comenzi.end(), std::inserter(orase, orase.end()));
    std::println("Orașe distincte: {}", orase);
}

Rezultat

Orașe distincte: {"Arad", "Cluj", "Iași"}

Greșeli frecvente

  • Dai ca destinație rezultat.begin() pentru un vector gol: algoritmul scrie în afara vectorului (comportament nedefinit). Folosește std::back_inserter(rezultat) sau fă întâi resize.
  • Faci reserve și apoi copiezi la v.begin(). reserve nu creează elemente; tot ai nevoie de back_inserter.

Comenzi înrudite

  • std::vector::push_back: Adaugă un element la sfârșitul vectorului; vectorul crește cu o poziție.
  • std::copy: Copiază elementele unui interval (copy) sau primele n elemente (copy_n) la o destinație.
  • std::transform: Aplică o funcție fiecărui element și scrie rezultatele în alt interval (sau în același).
  • std::set::insert: Adaugă o valoare în set dacă nu există deja și spune prin rezultat dacă a fost adăugată.