Middle
Co se děje s prvky std::vector při operaci realloc?
sobes.tech AI
Odpověď od AI
std::vector nepoužívá realloc. Při změně velikosti kontejneru, která vyžaduje přerozdělení paměti, se děje následující:
- Vyhradí se nová oblast paměti dostatečné velikosti.
- Elementy z staré oblasti se přesunou do nové.
- U typů podporujících přesunovou semantiku (
Ts korektní implementací konstruktoru přesunu a/nebo operátoru přiřazení přesunu) se použije přesun. To je efektivnější, protože staré zdroje (například paměť alokovaná uvnitř objektů) jsou předány novým objektům a staré objekty zůstanou v platném, ale neurčitelném stavu nebo jsou zničeny destruktory. - U typů, které nepodporují přesun nebo pokud překladač nemůže přesun použít, se použije kopírování.
- Pokud jsou prvky triviálně kopírovatelné (
Tje POD typ nebo má triviální operace kopírování a přesunu), může být použita funkcememcpynebo podobná nízkoúrovňová funkce pro rychlé kopírování surových dat.
- U typů podporujících přesunovou semantiku (
- Destruktory jsou volány pro prvky ve staré oblasti paměti.
- Staré oblasti paměti jsou uvolněny.
Je důležité poznamenat, že ukazatele a odkazy na prvky ve staré oblasti paměti se po přerozdělení stanou neplatnými.
#include <vector>
#include <iostream>
#include <string>
struct MyItem {
std::string name;
// Konstruktor
MyItem(const std::string& n) : name(n) {
std::cout << "Constructing " << name << std::endl;
}
// Konstruktor kopírování
MyItem(const MyItem& other) : name(other.name) {
std::cout << "Copying " << name << std::endl;
}
// Operátor přiřazení kopírováním
MyItem& operator=(const MyItem& other) {
if (this != &other) {
name = other.name;
std::cout << "Copy assigning " << name << std::endl;
}
return *this;
}
// Konstruktor přesunu
MyItem(MyItem&& other) noexcept : name(std::move(other.name)) {
std::cout << "Moving " << name << std::endl;
}
// Operátor přiřazení přesunem
MyItem& operator=(MyItem&& other) noexcept {
if (this != &other) {
name = std::move(other.name);
std::cout << "Move assigning " << name << std::endl;
}
return *this;
}
// Destruktor
~MyItem() {
std::cout << "Destroying " << name << std::endl;
}
};
int main() {
std::vector<MyItem> items;
items.reserve(2); // Rezervace paměti pro 2 prvky
items.emplace_back("item1"); // Bez reallokace
items.emplace_back("item2"); // Bez reallokace
std::cout << "Adding third item, triggering realloc-like operation:" << std::endl;
items.emplace_back("item3"); // Vyžaduje reallokaci
// Výstup ukáže přesun prvků item1 a item2, následně destrukci starých objektů
// a konstrukci nového item3.
// Pokud by MyItem nepodporoval přesun, byla by výstup o kopírování.
return 0;
}