Middle
Wat gebeurt er met de elementen van std::vector tijdens de realloc-operatie?
sobes.tech AI
Antwoord van AI
std::vector gebruikt geen realloc. Wanneer de grootte van de container wordt gewijzigd en geheugen opnieuw moet worden toegewezen, gebeurt het volgende:
- Er wordt een nieuw geheugenblok van voldoende grootte toegewezen.
- De elementen uit het oude blok worden naar het nieuwe verplaatst.
- Voor typen die de move-semantiek ondersteunen (
Tmet een correct geïmplementeerde move-constructeur en/of move-toewijzingsoperator), wordt de move gebruikt. Dit is efficiënter, omdat de oude resources (bijvoorbeeld geheugen dat binnen objecten is toegewezen) worden overgedragen aan de nieuwe objecten, en de oude objecten in een geldige maar ongedefinieerde staat blijven of worden schoongemaakt door destructors. - Voor typen die geen move-semantiek ondersteunen of als de compiler de move niet kan toepassen, wordt kopiëren gebruikt.
- Als de elementen triviaal kopieerbaar zijn (
Tis een POD-type of heeft triviale kopieer- en move-operaties), kunnenmemcpyof vergelijkbare low-level functies worden gebruikt om de ruwe gegevens snel te kopiëren.
- Voor typen die de move-semantiek ondersteunen (
- De destructors worden aangeroepen voor de elementen in het oude geheugen.
- Het oude geheugen wordt vrijgegeven.
Het is belangrijk op te merken dat pointers en referenties naar elementen in het oude geheugen ongeldig worden na de herverdeling.
#include <vector>
#include <iostream>
#include <string>
struct MyItem {
std::string name;
// Constructor
MyItem(const std::string& n) : name(n) {
std::cout << "Constructing " << name << std::endl;
}
// Kopieerconstructor
MyItem(const MyItem& other) : name(other.name) {
std::cout << "Copying " << name << std::endl;
}
// Kopieer toewijzingsoperator
MyItem& operator=(const MyItem& other) {
if (this != &other) {
name = other.name;
std::cout << "Copy assigning " << name << std::endl;
}
return *this;
}
// Move constructor
MyItem(MyItem&& other) noexcept : name(std::move(other.name)) {
std::cout << "Moving " << name << std::endl;
}
// Move toewijzingsoperator
MyItem& operator=(MyItem&& other) noexcept {
if (this != &other) {
name = std::move(other.name);
std::cout << "Move assigning " << name << std::endl;
}
return *this;
}
// Destructor
~MyItem() {
std::cout << "Destroying " << name << std::endl;
}
};
int main() {
std::vector<MyItem> items;
items.reserve(2); // Reserveer ruimte voor 2 elementen
items.emplace_back("item1"); // Zonder realloc
items.emplace_back("item2"); // Zonder realloc
std::cout << "Derde item toevoegen, activeert realloc-achtige operatie:" << std::endl;
items.emplace_back("item3"); // Vereist realloc
// De uitvoer toont verplaatsing voor item1 en item2, gevolgd door destructie van oude objecten
// en constructie van het nieuwe item3.
// Als MyItem geen move-ondersteuning heeft, wordt kopiëren weergegeven.
return 0;
}