std::vector::emplace_back în C++

std::vector C++11

Construiește un element nou direct la sfârșitul vectorului, din argumentele constructorului.

Sintaxă
template<class... Args>
T& emplace_back(Args&&... argumente);   // returnează referință din C++17

Ce face std::vector::emplace_back

emplace_back face același lucru ca push_back (adaugă la final), dar primește argumentele constructorului, nu un obiect gata făcut. Obiectul este construit direct în memoria vectorului, fără un obiect temporar care să fie apoi mutat sau copiat.

Diferența contează pentru obiecte mai mari sau care nu se pot copia. Pentru int sau pentru un obiect pe care îl ai deja, push_back și emplace_back sunt la fel de bune. Din C++17, emplace_back returnează o referință la elementul nou.

Regulile de invalidare sunt aceleași ca la push_back: dacă se realocă memoria, toți iteratorii și referințele vechi devin invalide.

Parametri

Parametru Descriere
argumente Valorile date constructorului tipului T.

Ce returnează

O referință la elementul tocmai construit (din C++17; în C++11/14 nu returna nimic).

Exemple

Exemplul 1: Construirea produselor direct în vector

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

struct Produs {
    std::string nume;
    double pret;
    Produs(std::string n, double p) : nume(std::move(n)), pret(p) {}
};

int main() {
    std::vector<Produs> raft;
    raft.emplace_back("Lapte", 6.5);          // construit pe loc
    raft.emplace_back("Pâine", 4.2);
    raft.push_back(Produs("Ouă", 13.9));      // obiect temporar, apoi mutat

    for (const auto& p : raft) {
        std::println("{:<6} {:>6.2f} lei", p.nume, p.pret);
    }
}

Rezultat

Lapte    6.50 lei
Pâine    4.20 lei
Ouă     13.90 lei

Exemplul 2: Folosirea referinței returnate

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

int main() {
    std::vector<std::string> nume;
    std::string& ultimul = nume.emplace_back(5, '*');   // std::string(5, '*')
    ultimul += " Ana";
    std::println("{}", nume);
}

Rezultat

["***** Ana"]

Greșeli frecvente

  • Crezi că emplace_back este mereu mai rapid. Pentru un obiect existent (v.emplace_back(x)) se face tot o copie, exact ca la push_back(x).
  • Folosești emplace_back cu acolade: v.emplace_back({1, 2}) nu compilează, pentru că acoladele nu pot fi deduse ca argumente. Scrie argumentele fără acolade sau folosește push_back({1, 2}).

Comenzi înrudite

  • std::vector::push_back: Adaugă un element la sfârșitul vectorului; vectorul crește cu o poziție.
  • std::map::try_emplace: try_emplace adaugă doar dacă cheia lipsește; insert_or_assign adaugă sau înlocuiește și spune ce a făcut.