std::vector::emplace back
Főnév
std::vector::emplace back (tsz. std::vector::emplace backs)
1. Bevezetés a std::vector-ba és az elemek hozzáadásába
A C++ Standard Template Library (STL) egyik leggyakrabban használt konténer típusa a std::vector, amely dinamikusan méretezhető tömbként működik. A std::vector lehetővé teszi, hogy dinamikusan növeljük vagy csökkentsük az elemek számát, miközben az elemek tárolása folyamatos memóriaterületen történik.
Az elemek hozzáadására több lehetőség is van:
push_back(const T& val)— beszúr egy másolatot az elemről a vektor végére.push_back(T&& val)— mozgató (move) verzió, amely átveszi az objektum tulajdonjogát.emplace_back(Args&&... args)— új elemet hoz létre közvetlenül a helyén, a megadott paraméterek alapján.
Ez a három közül az emplace_back az egyik leghatékonyabb és legflexibilisebb módja az elemek hozzáadásának, különösen komplex osztályok esetén.
2. Mi az az emplace_back és hogyan működik?
A std::vector::emplace_back C++11-ben került bevezetésre, és egy olyan függvény, amely közvetlenül az adott paraméterekkel létrehozza az új elemet a vektor végén, anélkül, hogy egy külön objektumot először létrehoznánk, majd másolnánk vagy mozdítanánk be.
Alapvető működés
template <class... Args>
void emplace_back(Args&&... args);
- Az
emplace_backegy paramétercsomagot (Args&&...) vár, ami lehetővé teszi bármilyen számú és típusú argumentum továbbítását. - Ezekkel az argumentumokkal közvetlenül meghívja az elem típusának megfelelő konstruktorát a vektorban.
- A létrehozott elem azonnal a vektor belső tárolóhelyén jön létre, így elkerülhető a felesleges másolás vagy mozgatás.
Mire jó ez?
- Hatékonyabb, mint a
push_back: Nem kell először egy ideiglenes objektumot létrehozni, majd azt beszúrni. - Többféle konstruktor hívása: Olyan objektumok létrehozását teszi lehetővé, amelyekhez több vagy speciális konstruktor szükséges.
- Egyszerűbb és tisztább kód: Nem kell külön példányt létrehozni és azt beadni a vektorba.
3. Példa emplace_back használatára
Vegyünk egy egyszerű osztályt:
class Szemely {
public:
std::string nev;
int kor;
Szemely(const std::string& n, int k) : nev(n), kor(k) {
std::cout << "Szemely konstruktor: " << nev << ", " << kor << std::endl;
}
};
push_back használatával:
std::vector<Szemely> emberek;
Szemely s("Dani", 30);
emberek.push_back(s);
Ebben az esetben először létrejön az ideiglenes s objektum, majd másolás vagy mozgatás történik a vektorba.
emplace_back használatával:
std::vector<Szemely> emberek;
emberek.emplace_back("Dani", 30);
Itt közvetlenül a "Dani" és 30 argumentumokkal hívjuk meg a Szemely konstruktorát, az objektum a vektor memóriájában jön létre, nem kell külön példányt előállítani.
4. Technikai részletek, belső működés
- Az
emplace_backáltalában a vektor aktuális kapacitását ellenőrzi. - Ha a kapacitás nem elegendő az új elemhez, akkor új, nagyobb memóriaterületet foglal, és átmásolja vagy átmásolja a régi elemeket az új helyre.
- Ez a költséges rész független az
emplace_back-tól vagypush_back-tól, viszont azemplace_backsegítségével elkerülhető az ideiglenes objektum létrehozásának költsége. - Az
emplace_backtökéletes továbbítást (perfect forwarding) alkalmaz a paramétereken, így az argumentumokat optimálisan továbbítja a konstruktorhoz.
5. Mikor érdemes használni az emplace_back-et?
- Ha az osztályodnak többparaméteres vagy komplex konstruktorai vannak.
- Ha el akarod kerülni a fölösleges másolásokat vagy mozgatásokat.
- Ha egyszerűen és tömören akarsz új elemeket létrehozni a konténerben.
- Ha objektumot akarsz létrehozni anélkül, hogy előbb külön példányt kellene inicializálni.
6. Különbség emplace_back és push_back között
| Tulajdonság | push_back |
emplace_back |
|---|---|---|
| Paraméter típusa | Objektumot vagy rvalue referencia | Konstruktor paramétereket vár |
| Objektum létrehozás | Először objektum, majd másolás/mozgatás | Objektum közvetlenül a helyén jön létre |
| Hatékonyság | Lehet több felesleges másolás | Hatékonyabb, kevesebb felesleges művelet |
| Tökéletes továbbítás | Nem alkalmazza | Igen, tökéletes továbbítást használ |
| Kompatibilitás | Minden C++ verzióban elérhető | Csak C++11-től kezdve |
7. További példák
Objektum több paraméterrel
struct Pont {
int x, y, z;
Pont(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {}
};
std::vector<Pont> pontok;
pontok.emplace_back(10, 20, 30);
Beágyazott objektum létrehozása
class Auto {
public:
std::string marka;
int evjarat;
Auto(const std::string& m, int ev) : marka(m), evjarat(ev) {}
};
std::vector<Auto> autok;
autok.emplace_back("Toyota", 2020);
Ha az osztálynak nincs alapértelmezett konstruktor:
class Ertek {
int x;
public:
Ertek(int v) : x(v) {}
};
std::vector<Ertek> vektor;
vulkan.emplace_back(5); // push_back nem működne így alapértelmezett konstruktor nélkül
8. Tipikus hibák az emplace_back használatakor
- Nem megfelelő paraméterek átadása, amik nem egyeznek az adott típus konstruktoraival.
- Ha a konstruktor explicit, vagy olyan paramétereket vár, amiket nem adtunk meg.
- Elfelejtett C++11 vagy újabb szabvány használata, mert
emplace_backcsak C++11-től elérhető.
9. Összefoglaló
std::vector::emplace_backegy rugalmas, hatékony módszer új elemek létrehozására és hozzáadására egy vektor végéhez.- Megszünteti a felesleges másolásokat és mozgatásokat, mert közvetlenül a vektor által fenntartott memóriában hívja meg az elem konstruktorát.
- Használata egyszerűbb és tisztább kódot eredményez, különösen összetett típusok vagy több paraméteres konstruktorok esetén.
- Csak C++11 és újabb szabványokban érhető el.
10. Kódpélda összefoglalóval
#include <iostream>
#include <vector>
#include <string>
class Szemely {
public:
std::string nev;
int kor;
Szemely(const std::string& n, int k) : nev(n), kor(k) {
std::cout << "Szemely konstruktor: " << nev << ", " << kor << std::endl;
}
};
int main() {
std::vector<Szemely> emberek;
// push_back példány készítés után
Szemely s("Anna", 28);
emberek.push_back(s);
// emplace_back paraméterek közvetlen átadásával
emberek.emplace_back("Béla", 35);
std::cout << "Az emberek száma: " << emberek.size() << std::endl;
for (const auto& e : emberek) {
std::cout << e.nev << " (" << e.kor << " éves)" << std::endl;
}
return 0;
}
- std::vector::emplace back - Szótár.net (en-hu)
- std::vector::emplace back - Sztaki (en-hu)
- std::vector::emplace back - Merriam–Webster
- std::vector::emplace back - Cambridge
- std::vector::emplace back - WordNet
- std::vector::emplace back - Яндекс (en-ru)
- std::vector::emplace back - Google (en-hu)
- std::vector::emplace back - Wikidata
- std::vector::emplace back - Wikipédia (angol)