Sobes.tech
Middle

Mida juhtub std::vector elementidega realloc operatsiooni ajal?

sobes.tech AI

Vastus AI-lt

std::vector ne kasutab realloc. Kui konteineri suurus muutub ja see nõuab mälu ümberjaotamist, toimub järgmine:

  1. Vabastatakse uus mäluala sobiva suurusega.
  2. Elementidest vanas piirkonnas kopeeritakse või liigub need uude.
    • Kui tüübid toetavad liikumise semantikat (T koos korrektselt rakendatud liikumiskonstruktoriga ja/või liikumisega määramise operaatoriga), kasutatakse liikumist. See on tõhusam, kuna vanad ressursid (näiteks mälu, mis on määratud sisemistele objektidele) antakse uutele objektidele, ja vanad objektid jäävad kehtivaks, kuid määratlemata või tühjendatakse destruktoritega.
    • Kui tüübid ei toeta liikumist või kui kompilaator ei saa liikumist rakendada, kasutatakse koopiat.
    • Kui elemendid on triviaalne koopiatav (T on POD-tüüp või omab triviaalset koopimise ja liikumise operatsiooni), võib kasutada memcpy või sarnaseid madala taseme funktsioone, et kiiresti kopeerida töötlemata andmeid.
  3. Destructors kutsutakse vanade elementide jaoks.
  4. Vanad mäluressursid vabastatakse.

Oluline on märkida, et vanade elementide pointerid ja viited muutuvad kehtetuks pärast ümberjaotamist.

#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;
    }
    // Kopeerikonstruktor
    MyItem(const MyItem& other) : name(other.name) {
        std::cout << "Copying " << name << std::endl;
    }
    // Kopeerivõtja
    MyItem& operator=(const MyItem& other) {
        if (this != &other) {
            name = other.name;
            std::cout << "Copy assigning " << name << std::endl;
        }
        return *this;
    }
    // Liikumiskonstruktor
    MyItem(MyItem&& other) noexcept : name(std::move(other.name)) {
        std::cout << "Moving " << name << std::endl;
    }
    // Liikumisega määramise operaator
    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); // Vabastame ruumi kahe elemendi jaoks

    items.emplace_back("item1"); // Ei toimu ümberjaotust
    items.emplace_back("item2"); // Ei toimu ümberjaotust

    std::cout << "Kolmanda elemendi lisamine, käivitab realloc-like operatsiooni:" << std::endl;
    items.emplace_back("item3"); // Vajalik ümberjaotus
    // Väljund näitab liikumist item1 ja item2, siis vanade objektide destruktsiooni
    // ja uue item3 konstruktsiooni.
    // Kui MyItem ei toetaks liikumist, oleks väljund koopimisest.

    return 0;
}