Sobes.tech
Middle

Kas notiek ar std::vector elementiem realloc operācijas laikā?

sobes.tech AI

Atbilde no AI

std::vector ne izmanto realloc. Kad mainās konteineru izmērs, kas prasa atmiņas pārdali, notiek šādas darbības:

  1. Tiek piešķirta jauna atmiņas zona ar pietiekamu izmēru.
  2. Elementi no vecās zonas tiek pārvietoti uz jauno.
    • Ja tipi atbalsta pārvietošanas semantiku (T ar pareizi realizētu pārvietošanas konstruktoru un/vai pārvietošanas piešķiršanas operatoru), tiek izmantota pārvietošana. Tas ir efektīvāk, jo vecie resursi (piemēram, atmiņa, kas piešķirta iekšējiem objektiem) tiek nodoti jaunajiem objektiem, bet vecie objekti paliek derīgi, bet nenoteiktā stāvoklī vai tiek iztīrīti ar destruktoru.
    • Ja tipi nepārstāv pārvietošanu vai ja kompilators nevar piemērot pārvietošanu, tiek izmantota kopēšana.
    • Ja elementi ir trivāli kopējami (T ir POD tips vai tam ir trivālas kopēšanas un pārvietošanas operācijas), var tikt izmantota memcpy vai līdzīgas zema līmeņa funkcijas, lai ātri nokopētu neapstrādātus datus.
  3. Tiek izsaukti destruktori vecās zonas elementiem.
  4. Vecā zona tiek atbrīvota.

Svarīgi atzīmēt, ka norādītāji un atsauces uz vecās zonas elementiem kļūst nederīgas pēc pārdales.

#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;
    }
    // Kopēšanas konstruktors
    MyItem(const MyItem& other) : name(other.name) {
        std::cout << "Copying " << name << std::endl;
    }
    // Kopēšanas operators
    MyItem& operator=(const MyItem& other) {
        if (this != &other) {
            name = other.name;
            std::cout << "Copy assigning " << name << std::endl;
        }
        return *this;
    }
    // Pārvietošanas konstruktors
    MyItem(MyItem&& other) noexcept : name(std::move(other.name)) {
        std::cout << "Moving " << name << std::endl;
    }
    // Pārvietošanas operators
    MyItem& operator=(MyItem&& other) noexcept {
        if (this != &other) {
            name = std::move(other.name);
            std::cout << "Move assigning " << name << std::endl;
        }
        return *this;
    }
    // Destruktors
    ~MyItem() {
        std::cout << "Destroying " << name << std::endl;
    }
};

int main() {
    std::vector<MyItem> items;
    items.reserve(2); // Rezervē vietu 2 elementiem

    items.emplace_back("item1"); // Nav pārdale
    items.emplace_back("item2"); // Nav pārdale

    std::cout << "Pievienojot trešo elementu, tiek aktivizēta realloc-like operācija:" << std::endl;
    items.emplace_back("item3"); // Ir nepieciešama pārdale
    // Izvade parādīs pārvietošanu item1 un item2, pēc tam veco objektu destrukciju
    // un jauno item3 konstrukciju.
    // Ja MyItem nepārstāv pārvietošanu, tiks parādīta kopēšana.

    return 0;
}

Tādējādi notiek elementu pārvietošana vai kopēšana uz jauno zonu, pēc tam to destrukcija vecajā zonā.