Sobes.tech
Middle

Kādas pamata dēļ vairāki shared_ptr objekti var atsaukties uz to pašu norādītāju?

sobes.tech AI

Atbilde no AI

Dažas std::shared_ptr objekti varētu atsaukties uz to pašu norādi, pateicoties kontroles blokam (control block).

Kontroles bloks, kas ir saistīts ar pārvaldāmo objektu, satur:

  • Stipro atsauces skaitītāju (strong reference count): Palielinās, kad tiek izveidots jauns shared_ptr tam pašam objektam. Samazinās, kad shared_ptr tiek iznīcināts. Kad tas sasniedz nulli, saistītais objekts (norāde) tiek dzēsts.
  • Vāju atsauces skaitītāju (weak reference count): Pielietojams std::weak_ptr. Palielinās, kad weak_ptr tiek izveidots no shared_ptr. Samazinās, kad weak_ptr tiek iznīcināts. Kad abi skaitītāji ir nulle, kontrolējošais bloks tiek dzēsts.
  • Paša pārvaldāmā objekta norāde: Ne dati, bet norāde, ko pārvalda bloks.

Kad jūs izveidojat shared_ptr no esoša shared_ptr (kopēšana, piešķiršana ar kopēšanu), tie sāk izmantot to pašu kontrolējošo bloku, un stipro atsauces skaitītājs šajā blokā palielinās.

Piemērs:

#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() {
    // Pirmā `shared_ptr` izveide:
    // Tiek izveidots kontrolējošais bloks un objekts MyData:
    // stiprais skaitītājs: 1, vājais: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";

    // Otrs `shared_ptr` no ptr1:
    // Izmanto to pašu kontrolējošo bloku:
    // stiprais skaitītājs palielinās līdz 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šais `shared_ptr` no ptr1:
    // Izmanto to pašu kontrolējošo bloku:
    // stiprais skaitītājs palielinās līdz 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 << "Iziet no apgabala.\n";
    // ptr3 iziet no apgabala:
    // stiprais skaitītājs samazinās līdz 2.
    // ptr2 iziet no apgabala:
    // stiprais skaitītājs samazinās līdz 1.
    // ptr1 iziet no apgabala:
    // stiprais skaitītājs samazinās līdz 0.
    // Objekts MyData tiek dzēsts.
    // Kontrolējošais bloks tiek izdzēsts.
}

Katrs shared_ptr objekts satur savu norādi uz kontrolējošo bloku un savu norādi uz datu objektu. Kopējot shared_ptr, tiek kopēti abi norādītāji, un stipro atsauces skaitītājs kopīgajā blokā palielinās. Tādējādi visi shared_ptr norāda uz to pašu kontrolējošo bloku, kas uzrauga to kopiju skaitu un nosaka brīža, kad jāatbrīvo pārvaldītais resurss.