Sobes.tech
Middle

Ինչ հիմքով մի քանի shared_ptr օբյեկտներ կարող են հղում կատարել նույն ցուցիչին:

sobes.tech AI

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

Որոշ std::shared_ptr օբյեկտներ կարող են հղում ունենալ նույն ցուցիչին՝ շնորհիվ կառավարական բլոկի (control block) առկայության:

Կառավարական բլոկը, որը կապված է կառավարվող օբյեկտի հետ, պարունակում է.

  • Հզոր հղումների հաշվիչ (strong reference count): Բարձրանում է, երբ ստեղծվում է նոր shared_ptr նույն օբյեկտի համար: Կրճատվում է, երբ shared_ptr-ը ոչնչացվում է: Երբ հասնում է զրոյի, կապված օբյեկտը (ցուցակը) ջնջվում է:
  • Թույլ հղումների հաշվիչ (weak reference count): Օգտագործվում է std::weak_ptr-ի համար: Բարձրանում է, երբ weak_ptr-ը ստեղծվում է shared_ptr-ից: Կրճատվում է, երբ weak_ptr-ը ոչնչացվում է: Երբ երկու հաշվիչներն էլ զրոյին հասնեն, կառավարման բլոկը ջնջվում է:
  • Ինքնին ցուցիչ կառավարվող օբյեկտի վրա: Ոչ տվյալների ցուցիչը, այլ այն, որը կառավարում է բլոկը:

Երբ ստեղծում եք shared_ptr՝ գոյություն ունեցող shared_ptr-ից (կոպիա, նշանակում-կոպիա), նրանք սկսում են օգտագործել նույն կառավարման բլոկը, և ուժեղ հղումների հաշվիչը այդ բլոկում ավելանում է:

Օրինակ՝

#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() {
    // Առաջին `shared_ptr`-ի ստեղծում:
    // Կառավարական բլոկ և MyData օբյեկտ ստեղծվում են:
    // ուժեղ հաշվիչը՝ 1, թույլ՝ 0:
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";

    // Երկրորդ `shared_ptr`-ի ստեղծում ptr1-ից:
    // Օգտագործում է նույն կառավարման բլոկը:
    // ուժեղ հաշվիչը՝ 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";

    // Երրորդ `shared_ptr`-ի ստեղծում ptr1-ից:
    // Օգտագործում է նույն կառավարման բլոկը:
    // ուժեղ հաշվիչը՝ 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 << "Դուրս գալու սահմանից.\n";
    // ptr3 դուրս է գալիս սահմանից:
    // ուժեղ հաշվիչը՝ 2:
    // ptr2 դուրս է գալիս սահմանից:
    // ուժեղ հաշվիչը՝ 1:
    // ptr1 դուրս է գալիս սահմանից:
    // ուժեղ հաշվիչը՝ 0:
    // MyData օբյեկտը ջնջվում է:
    // Կառավարական բլոկը ջնջվում է:
}

Յուրաքանչյուր shared_ptr օբյեկտ ունի իր ցուցիչը կառավարման բլոկին և իր ցուցիչը տվյալների օբյեկտին: Երբ shared_ptr-ը կոպիա է, երկու ցուցիչներն էլ կոպիացվում են, և ուժեղ հղումների հաշվիչը մեծանում է ընդհանուր բլոկում: Այսպիսով, բոլոր shared_ptr-երը ցույց են տալիս նույն կառավարման բլոկին, որը հետևում է սեփականության օրինակների քանակին և որոշում է կառավարվող ռեսուրսի ազատման պահը։