Sobes.tech
Middle

Kokiu pagrindu keli shared_ptr objektai gali nurodyti tą patį rodyklį?

sobes.tech AI

Atsakymas iš AI

Keli std::shared_ptr objektai gali nurodyti į tą patį rodyklę dėl valdymo bloko (control block) buvimo.

Valdymo blokas, susijęs su valdomu objektu, turi:

  • Stiprių nuorodų skaitiklis (strong reference count): Didėja, kai kuriamas naujas shared_ptr tam pačiam objektui. Mažėja, kai shared_ptr sunaikinamas. Kai pasiekia nulį, susietas objektas (rodyklė) yra ištrinamas.
  • Silpnų nuorodų skaitiklis (weak reference count): Naudojamas std::weak_ptr. Didėja, kai weak_ptr sukuriamas iš shared_ptr. Mažėja, kai weak_ptr sunaikinamas. Kai abu skaitikliai pasiekia nulį, valdymo blokas yra ištrinamas.
  • Savyje esantis rodyklė į valdomą objektą: Ne duomenų rodyklė, o ta, kuri valdomo bloko.

Kai sukuriate shared_ptr iš esamo shared_ptr (kopijavimas, priskyrimas kopijavimu), jie pradeda naudoti tą patį valdymo bloką, ir stiprių nuorodų skaitiklis šiame bloke didėja.

Pavyzdys:

#include <memory>
#include <iostream>

struct MyData {
    int value;
    MyData(int v) : value(v) { std::cout << "MyData(" << value << ") created.\n"; }
    ~MyData() { std::cout << "MyData(" << value << ") destroyed.\n"; }
};

int main() {
    // Pirmas `shared_ptr` sukūrimas:
    // Sukuriamas valdymo blokas ir MyData objektas:
    // stiprių skaitiklis: 1, silpnų: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";

    // Antras `shared_ptr` sukūrimas iš ptr1:
    // Naudojamas tas pats valdymo blokas:
    // stiprių skaitiklis padidėja iki 2.
    std::shared_ptr<MyData> ptr2 = ptr1;
    std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
    std::cout << "ptr2 use count: " << ptr2.use_count() << "\n";

    // Trečias `shared_ptr` sukūrimas iš ptr1:
    // Naudojamas tas pats valdymo blokas:
    // stiprių skaitiklis padidėja iki 3.
    std::shared_ptr<MyData> ptr3 = ptr1;
     std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
    std::cout << "ptr2 use count: " << ptr2.use_count() << "\n";
    std::cout << "ptr3 use count: " << ptr3.use_count() << "\n";

    std::cout << "Išeiti iš apimties.\n";
    // ptr3 išeina iš apimties:
    // stiprių skaitiklis sumažėja iki 2.
    // ptr2 išeina iš apimties:
    // stiprių skaitiklis sumažėja iki 1.
    // ptr1 išeina iš apimties:
    // stiprių skaitiklis sumažėja iki 0.
    // MyData objektas sunaikinamas.
    // Valdymo blokas ištrinamas.
}

Kiekvienas shared_ptr objektas turi savo nuorodą į valdymo bloką ir savo nuorodą į duomenų objektą. Kopijuojant shared_ptr, kopijuojami abu šie rodyklės, ir stiprių nuorodų skaitiklis bendrame bloke didėja. Taip visi shared_ptr nurodo į tą patį valdymo bloką, kuris stebi jų kopijų skaičių ir nustato valdomo išteklių išlaisvinimo momentą.