Sobes.tech
Middle

Millisel alusel võivad mitu shared_ptr objekti viidata samale näidisele?

sobes.tech AI

Vastus AI-lt

Mõned std::shared_ptr objektid võivad viidata samale näidisele tänu kontrollibloki (control block) olemasolule.

Kontrolliblokk, mis on seotud hallatava objektiga, sisaldab:

  • Tugevate viidete loendur (strong reference count): Kasvab, kui luuakse uus shared_ptr sama objekti jaoks. Väheneb, kui shared_ptr hävib. Kui see jõuab nulli, eemaldatakse seotud objekt (näidik).
  • Nõrkade viidete loendur (weak reference count): Kasutatakse std::weak_ptr jaoks. Kasvab, kui weak_ptr luuakse shared_ptr-st. Väheneb, kui weak_ptr hävib. Kui mõlemad loendurid jõuavad nulli, eemaldatakse kontrolliblokk.
  • Oma näidik hallatava objekti kohta: Mitte andmete näidik, vaid see, mida kontrolliblokk haldab.

Kui loote shared_ptr olemasolevast shared_ptr-st (kopeerimine, omistamine kopeerimisega), hakkavad nad kasutama sama kontrolliblokki ning tugeva viidete loendur selles blokis suureneb.

Näide:

#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() {
    // Esimese `shared_ptr` loomine:
    // Loob kontrollibloki ja MyData objekti:
    // tugevad loendurid: 1, nõrgad: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";

    // Teise `shared_ptr` loomine ptr1-st:
    // Kasutatakse sama kontrollibloki:
    // tugevate loendur tõuseb 2-le.
    std::shared_ptr<MyData> ptr2 = ptr1;
    std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
    std::cout << "ptr2 use count: " << ptr2.use_count() << "\n";

    // Kolmanda `shared_ptr` loomine ptr1-st:
    // Kasutatakse sama kontrollibloki:
    // tugevate loendur tõuseb 3-le.
    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 << "Väljumine ulatusest.\n";
    // ptr3 väljub ulatusest:
    // tugevate loendurite arv väheneb 2-le.
    // ptr2 väljub ulatusest:
    // tugevate loendurite arv väheneb 1-le.
    // ptr1 väljub ulatusest:
    // tugevate loendurite arv väheneb 0-le.
    // MyData objekt hävib.
    // Kontrolliblokk eemaldatakse.
}

Iga shared_ptr objekt sisaldab oma viidet kontrolliblokile ja oma viidet andmete objektile. Kopeerimisel kopeeritakse mõlemad viited ning selle ühise bloki tugevate viidete arv suureneb. Nii viitavad kõik shared_ptr-d samale kontrolliblokile, mis jälgib nende koopiate arvu ning määrab hallatava ressursi vabastamise hetke.