std::vector::insert în C++

std::vector C++98

Inserează unul sau mai multe elemente înaintea unei poziții din vector; emplace construiește elementul pe loc.

Sintaxă
iterator insert(const_iterator poz, const T& valoare);
iterator insert(const_iterator poz, size_type n, const T& valoare);
iterator insert(const_iterator poz, InputIt prim, InputIt ultim);
iterator insert(const_iterator poz, std::initializer_list<T> lista);

iterator emplace(const_iterator poz, Args&&... argumente);   // C++11

Ce face std::vector::insert

insert pune elemente noi înaintea iteratorului poz. Toate elementele de la poz încolo se mută cu o poziție (sau cu n poziții) spre dreapta, deci inserarea la început sau la mijloc durează proporțional cu numărul de elemente mutate. insert(v.end(), x) este echivalent cu push_back(x).

emplace(poz, argumente...) face același lucru pentru un singur element, dar îl construiește direct din argumentele constructorului, ca emplace_back.

Invalidare: dacă inserarea realocă memoria (nu mai este loc), toți iteratorii și referințele devin invalide. Dacă nu realocă, devin invalide cele de la poz încolo. De aceea, insert returnează un iterator nou, valid, la primul element inserat: folosește-l pe acela.

Parametri

Parametru Descriere
poz Iterator: elementele noi se pun înaintea lui. begin() = la început, end() = la final.
valoare / n Valoarea de inserat și, opțional, de câte ori.
prim, ultim Un interval din alt container, copiat în vector.
lista O listă între acolade: {1, 2, 3}.

Ce returnează

Un iterator la primul element inserat (sau poz, dacă nu s-a inserat nimic).

Exemple

Exemplul 1: Inserare la început, la mijloc și din alt vector

#include <print>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> traseu{"București", "Brașov", "Cluj"};
    traseu.insert(traseu.begin() + 1, "Ploiești");          // înainte de Brașov
    traseu.insert(traseu.begin(), "Constanța");             // la început
    std::println("{}", traseu);

    std::vector<std::string> extra{"Oradea", "Arad"};
    traseu.insert(traseu.end(), extra.begin(), extra.end()); // la final
    std::println("{}", traseu);

    std::vector<int> v{1, 5};
    v.insert(v.begin() + 1, {2, 3, 4});
    v.insert(v.end(), 3, 0);                                // trei zerouri
    std::println("{}", v);
}

Rezultat

["Constanța", "București", "Ploiești", "Brașov", "Cluj"]
["Constanța", "București", "Ploiești", "Brașov", "Cluj", "Oradea", "Arad"]
[1, 2, 3, 4, 5, 0, 0, 0]

Exemplul 2: Folosește iteratorul returnat

După fiecare inserare iteratorul vechi poate fi invalid. Reținem cel returnat de insert și sărim peste elementul nou cu ++it.

#include <print>
#include <vector>

int main() {
    std::vector<int> v{1, 2, 3, 4};
    // Inserăm un 0 înaintea fiecărui număr par.
    for (auto it = v.begin(); it != v.end(); ++it) {
        if (*it % 2 == 0) {
            it = v.insert(it, 0);   // it indică acum 0-ul nou
            ++it;                   // înapoi la numărul par
        }
    }
    std::println("{}", v);
}

Rezultat

[1, 0, 2, 3, 0, 4]

Exemplul 3: emplace la o poziție

#include <print>
#include <string>
#include <utility>
#include <vector>

int main() {
    std::vector<std::pair<std::string, int>> clasament{{"Ana", 95}, {"Ion", 80}};
    clasament.emplace(clasament.begin() + 1, "Elena", 88);   // pair construit pe loc
    for (const auto& [nume, puncte] : clasament) {
        std::println("{}: {}", nume, puncte);
    }
}

Rezultat

Ana: 95
Elena: 88
Ion: 80

Greșeli frecvente

  • Continui să folosești iteratorul vechi după insert: v.insert(it, x); ++it;. Dacă s-a realocat memoria, it este invalid (comportament nedefinit). Scrie it = v.insert(it, x);.
  • Inserezi des la începutul unui vector mare. Fiecare inserare mută tot vectorul. Dacă adaugi des în față, folosește std::deque, sau adaugă la final și inversează la sfârșit.
  • Inserezi elementele vectorului în el însuși cu un interval (v.insert(v.begin(), v.begin(), v.end())). Iteratorii sursei nu au voie să provină din același vector: comportament nedefinit.

Comenzi înrudite

  • std::vector::erase: Șterge un element sau un interval de elemente din vector și returnează iteratorul elementului de după.
  • std::vector::push_back: Adaugă un element la sfârșitul vectorului; vectorul crește cu o poziție.
  • std::vector::emplace_back: Construiește un element nou direct la sfârșitul vectorului, din argumentele constructorului.
  • std::deque: Coadă cu două capete: adăugare și ștergere rapidă atât la început, cât și la sfârșit, plus acces după poziție.