Sobes.tech
Middle

Mi történik a std::vector elemeivel realloc művelet során?

sobes.tech MI

Válasz az MI-től

A std::vector nem használ realloc-ot. Amikor a konténer mérete változik, ami memória újraelosztást igényel, a következő történik:

  1. Egy új memória területet foglalunk le megfelelő méretben.
  2. A régi memória területről az elemek átkerülnek az újsára.
    • Olyan típusok esetén, amelyek támogatják a mozgató értékelést (T helyes mozgató konstruktorral és/vagy mozgató értékadó operátorral), a mozgatás történik. Ez hatékonyabb, mivel a régi erőforrásokat (pl. a belső memóriát) átadják az új objektumoknak, és a régi objektumok érvényes, de nem meghatározott állapotban maradnak vagy destruktorral tisztítódnak.
    • Olyan típusok esetén, amelyek nem támogatják a mozgató értékelést, vagy a fordító nem tudja alkalmazni a mozgatást, másolás történik.
    • Ha az elemek triválisan másolhatók (T POD típus vagy trivális másolási és mozgatási műveletekkel rendelkező típus), akkor memcpy vagy hasonló alacsony szintű függvények használhatók az adatok gyors másolására.
  3. A régi memória területen lévő elemek destruktorai meghívódnak.
  4. A régi memória terület felszabadul.

Fontos megjegyezni, hogy a régi memóriaelemekre mutató pointerek és hivatkozások érvénytelenek lesznek az újraelosztás után.

#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;
    }
    // Másoló konstruktor
    MyItem(const MyItem& other) : name(other.name) {
        std::cout << "Copying " << name << std::endl;
    }
    // Másoló értékadó operátor
    MyItem& operator=(const MyItem& other) {
        if (this != &other) {
            name = other.name;
            std::cout << "Copy assigning " << name << std::endl;
        }
        return *this;
    }
    // Mozgató konstruktor
    MyItem(MyItem&& other) noexcept : name(std::move(other.name)) {
        std::cout << "Moving " << name << std::endl;
    }
    // Mozgató értékadó operátor
    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); // Memória lefoglalása 2 elemre

    items.emplace_back("item1"); // Nincs reallokáció
    items.emplace_back("item2"); // Nincs reallokáció

    std::cout << "Adding third item, triggering realloc-like operation:" << std::endl;
    items.emplace_back("item3"); // Reallokáció szükséges
    // A kimenet mutatni fogja a mozgatást az item1 és item2 esetében, majd a régi objektumok destrukcióját
    // és az új item3 konstrukcióját.
    // Ha a MyItem nem támogatná a mozgatást, akkor másolási üzenet jelenne meg.

    return 0;
}

Így történik az elemek mozgatása vagy másolása az új memória területre, majd azok destrukciója a régi helyen.