Ce face std::vector::push_back
push_back pune o copie a valorii (sau valoarea mutată, dacă este temporară) după ultimul element. Este modul obișnuit de a construi un vector pas cu pas, de exemplu când citești date.
Vectorul are o capacitate rezervată (capacity()). Cât timp mai este loc, push_back doar scrie elementul. Când capacitatea este plină, vectorul alocă o zonă mai mare, mută toate elementele acolo și eliberează zona veche. De aceea, în medie, adăugarea la final este rapidă, dar uneori costă mai mult.
Atenție la invalidarea iteratorilor: dacă push_back realocă memoria, toate iteratorii, pointerii și referințele la elementele vectorului devin invalide. Dacă nu realocă, devine invalid doar end().
Parametri
| Parametru | Descriere |
|---|---|
valoare |
Elementul de adăugat. Trebuie să aibă tipul elementelor vectorului (sau să poată fi convertit la el). |
Ce returnează
Nimic (void). Noul element este v.back().
Exemple
Exemplul 1: Construirea unei liste de cumpărături
#include <print>
#include <string>
#include <vector>
int main() {
std::vector<std::string> cos;
cos.push_back("mere");
cos.push_back("brânză");
std::string produs = "cafea";
cos.push_back(produs); // se copiază
std::println("{} produse: {}", cos.size(), cos);
std::println("Ultimul adăugat: {}", cos.back());
}
Rezultat
3 produse: ["mere", "brânză", "cafea"]
Ultimul adăugat: cafea
Exemplul 2: Când se realocă memoria
Afișăm capacitatea după fiecare adăugare. Creșterea exactă (aici dublare) depinde de implementarea bibliotecii; rezultatul este cel de pe libc++ (clang).
#include <print>
#include <vector>
int main() {
std::vector<int> v;
for (int i = 1; i <= 9; ++i) {
std::size_t inainte = v.capacity();
v.push_back(i);
if (v.capacity() != inainte) {
std::println("size {}: capacitatea a crescut de la {} la {} (realocare)", v.size(), inainte, v.capacity());
}
}
}
Rezultat
size 1: capacitatea a crescut de la 0 la 1 (realocare)
size 2: capacitatea a crescut de la 1 la 2 (realocare)
size 3: capacitatea a crescut de la 2 la 4 (realocare)
size 5: capacitatea a crescut de la 4 la 8 (realocare)
size 9: capacitatea a crescut de la 8 la 16 (realocare)
Exemplul 3: Iterator păstrat corect după adăugare
Un iterator vechi nu mai este sigur după push_back. Soluția simplă: păstrează poziția (indicele), nu iteratorul, și calculează iteratorul din nou când ai nevoie.
#include <print>
#include <vector>
int main() {
std::vector<int> v{10, 20, 30};
std::size_t poz = 1; // vrem să urmărim elementul 20
for (int i = 0; i < 100; ++i) {
v.push_back(i); // poate realoca de mai multe ori
}
auto it = v.begin() + static_cast<std::ptrdiff_t>(poz); // iterator nou, valid
std::println("Elementul urmărit: {}", *it);
std::println("Vectorul are acum {} elemente", v.size());
}
Rezultat
Elementul urmărit: 20
Vectorul are acum 103 elemente
Greșeli frecvente
- Păstrezi un iterator, pointer sau referință la un element (
int& primul = v[0];) și apoi facipush_back. Dacă vectorul a realocat,primularată spre memorie eliberată: comportament nedefinit. - Adaugi în vector în timp ce îl parcurgi cu
for (int x : v). Bucla folosește iteratori, care pot fi invalidați. Parcurge cu indice și salvează dimensiunea înainte, sau adaugă într-un vector separat. - Faci mii de
push_backcând știi dinainte câte elemente vor fi. Apelează întâireserve(n)ca să eviți realocările repetate.
Comenzi înrudite
std::vector::emplace_back: Construiește un element nou direct la sfârșitul vectorului, din argumentele constructorului.std::vector::pop_back: Șterge ultimul element al vectorului; dimensiunea scade cu 1.std::vector::reserve: reserve() rezervă memorie pentru n elemente, capacity() spune cât loc este rezervat, iar shrink_to_fit() cere eliberarea locului nefolosit.std::vector::insert: Inserează unul sau mai multe elemente înaintea unei poziții din vector; emplace construiește elementul pe loc.std::back_inserter: Iteratori de inserare: fiecare scriere prin back_inserter face push_back, iar prin inserter face insert la o poziție.