Sobes.tech
Middle

Ինչ է տեղի ունենում std::vector տարրերի հետ realloc գործողության ժամանակ?

sobes.tech AI

Պատասխան AI-ից

std::vector օգտագործում է realloc-ը չէ։ Երբ կոնտեյների չափը փոխվում է, ինչը պահանջում է հիշողության նոր բաշխում, տեղի են ունենում հետևյալը:

  1. Նոր հիշողության տարածք է հատկացվում համապատասխան չափով:
  2. Էլեմենտները տեղափոխվում են հին տարածքից նորին:
    • Տիպերի համար, որոնք աջակցում են տեղափոխման սեմանտիկային (T ճիշտ իրականացված տեղափոխման կոնստրուկտորով և/կամ տեղափոխման վերագրող օպերատորով), օգտագործվում է տեղափոխում։ Սա ավելի արդյունավետ է, քանի որ հին ռեսուրսները (օրինակ, հիշողությունը, որը հատկացվել է օբյեկտների ներսում) փոխանցվում են նոր օբյեկտներին, իսկ հին օբյեկտները մնում են վավեր, բայց անորոշ վիճակում կամ մաքրվում են դեստրուկտորներով:
    • Տիպերի համար, որոնք չեն աջակցում տեղափոխման սեմանտիկային կամ եթե կոմպիլյատորը չի կարող կիրառել տեղափոխումը, օգտագործվում է պատճենը:
    • Եթե էլեմենտները տրիվիալ պատճենվող են (T POD տիպ կամ ունի տրիվիալ պատճենման և տեղափոխման օպերացիաներ), կարող է օգտագործվել memcpy կամ նմանատիպ ցածր մակարդակի ֆունկցիաներ՝ անպատճառ տվյալների արագ պատճենման համար:
  3. Հին տարածքում գտնվող էլեմենտների դեստրուկտորները կանչվում են:
  4. Հին տարածքը ազատվում է:

Կարևոր է նշել, որ հին տարածքի էլեմենտների ցուցիչներն ու հղումները անթույլատրելի են դառնում նոր բաշխումից հետո:

#include <vector>
#include <iostream>
#include <string>

struct MyItem {
    std::string name;
    // Կոնստրուկտոր
    MyItem(const std::string& n) : name(n) {
        std::cout << "Constructing " << name << std::endl;
    }
    // Կոպի կոնստրուկտոր
    MyItem(const MyItem& other) : name(other.name) {
        std::cout << "Copying " << name << std::endl;
    }
    // Կոնստրուկտոր վերագրում
    MyItem& operator=(const MyItem& other) {
        if (this != &other) {
            name = other.name;
            std::cout << "Copy assigning " << name << std::endl;
        }
        return *this;
    }
    // Տեղափոխման կոնստրուկտոր
    MyItem(MyItem&& other) noexcept : name(std::move(other.name)) {
        std::cout << "Moving " << name << std::endl;
    }
    // Տեղափոխման վերագրող օպերատոր
    MyItem& operator=(MyItem&& other) noexcept {
        if (this != &other) {
            name = std::move(other.name);
            std::cout << "Move assigning " << name << std::endl;
        }
        return *this;
    }
    // Դեստրուկտոր
    ~MyItem() {
        std::cout << "Destroying " << name << std::endl;
    }
};

int main() {
    std::vector<MyItem> items;
    items.reserve(2); // Հիշողության պահպանում 2 էլեմենտի համար

    items.emplace_back("item1"); // Չի կատարվում reallocation
    items.emplace_back("item2"); // Չի կատարվում reallocation

    std::cout << "Adding third item, triggering realloc-like operation:" << std::endl;
    items.emplace_back("item3"); // Պահանջվում է reallocation
    // Արտածում ցույց կտա տեղափոխում item1 և item2, ապա հին օբյեկտների դեստրուկցիա
    // և նոր item3 կոնստրուկցիա:
    // Եթե MyItem-ն աջակցեր տեղափոխմանը, կցուցադրվեր տեղափոխում:

    return 0;
}