Sobes.tech
Middle

realloc operatsiyasi davomida std::vector elementlari bilan nima bo'ladi?

sobes.tech AI

AIdan javob

std::vector realloc-ni ishlamaydi. Kapsaytirilgan hajmi o'zgartirilganda, xotira qayta taqsimlanishini talab qiladigan holatda, quyidagilar yuz beradi:

  1. Yetarli o'lchamdagi yangi xotira maydoni ajratiladi.
  2. Eski maydondagi elementlar yangi maydonga ko'chiriladi.
    • Agar turlar harakat qilish semantikasi (T to'g'ri amalga oshirilgan harakat qilish konstruktor va/yoki harakat qilish tayinlash operatori bilan)ni qo'llab-quvvatlasa, harakat qilish ishlatiladi. Bu yanada samarali, chunki eski resurslar (masalan, ob'ekt ichida ajratilgan xotira) yangi ob'ektlarga o'tkaziladi va eski ob'ektlar valid holatda qoladi yoki destruktorlar bilan tozalanadi.
    • Harakat qilish semantikasi qo'llab-quvvatlamaydigan turlar yoki kompilator harakat qilishni qo'llay olmasa, nusxa ko'chirish ishlatiladi.
    • Elementlar trivially nusxa ko'chiriladigan bo'lsa (T POD tur yoki trivially nusxa ko'chirish va harakat qilish operatsiyalari bilan), memcpy yoki shunga o'xshash past darajadagi funksiyalar yordamida xom ma'lumotlar tezda nusxa ko'chirilishi mumkin.
  3. Eski xotira maydonidagi elementlar uchun destruktorlar chaqiriladi.
  4. Eski xotira maydoni bo'shatiladi.

Muhim: eski maydondagi elementlarga ishora qiluvchi ko'rsatkichlar va referenslar, qayta taqsimlashdan so'ng, amal qilishdan to'xtaydi.

#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;
    }
    // Nusxa ko'chirish konstruktor
    MyItem(const MyItem& other) : name(other.name) {
        std::cout << "Copying " << name << std::endl;
    }
    // Nusxa tayinlash operatori
    MyItem& operator=(const MyItem& other) {
        if (this != &other) {
            name = other.name;
            std::cout << "Copy assigning " << name << std::endl;
        }
        return *this;
    }
    // Harakat qilish konstruktor
    MyItem(MyItem&& other) noexcept : name(std::move(other.name)) {
        std::cout << "Moving " << name << std::endl;
    }
    // Harakat qilish tayinlash operatori
    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); // 2 ta element uchun ajratish

    items.emplace_back("item1"); // reallocsiz
    items.emplace_back("item2"); // reallocsiz

    std::cout << "Uchinchi element qo'shilmoqda, reallocga o'xshash operatsiya chaqirilmoqda:" << std::endl;
    items.emplace_back("item3"); // realloc talab qilinadi
    // Chiqarish, item1 va item2 uchun harakatni, eski ob'ektlarning destruksiyasini va yangi item3 konstruktsiyasini ko'rsatadi.
    // Agar MyItem harakat qilishni qo'llab-quvvatlamasa, nusxa ko'chirish ko'rsatiladi.

    return 0;
}