Sobes.tech
Middle
259

std::shared_ptr-дағы сілтеме санагыш қалай жұмыс істейді?

AI-дан жауап

sobes.tech AI

std::shared_ptr-тағы сілтеме есептегіш бөлек басқару блогында сақталады.

Басқару блогы құрылады:

  • std::shared_ptr көрсеткішінен алғаш рет жасалғанда.
  • Пайдаланушының жоюшысы немесе аллокаторы бар std::shared_ptr жасалғанда.
  • std::make_shared немесе std::allocate_shared қолданғанда.

Бұл басқару блогында кемінде екі есептегіш бар:

  1. Қатты сілтемелер есептегіші (strong count): std::shared_ptr жасалғанда немесе көшірілгенде өседі. std::shared_ptr жойылғанда кемиді. Бұл есептегіш нөлге айналғанда басқарылатын объекті босатылады.
  2. Әлсіз сілтемелер есептегіші (weak count): std::shared_ptr-дан std::weak_ptr жасалғанда өседі. std::weak_ptr жойылғанда кемиді. Басқару блогы екі есептегіш те нөлге айналғанда босатылады.

std::make_shared қолдану тікелей new-дан жасаудан артық, себебі ол объект пен басқару блогын бір блокта аллоцирлеуге мүмкіндік береді, бұл өнімділікті арттырады және фрагментацияны азайтады.

Атомар есептегіштер std::shared_ptr-ды көп ағынды сценарийлерде қауіпсіз етеді, дегенмен басқарылатын объектіге қол жеткізу әдепкі бойынша синхрондалмаған.

Мысал:

#include <iostream>
#include <memory>

struct MyObject {
    int data;
    MyObject(int d) : data(d) {
        std::cout << "MyObject(" << data << ") жасалды\n";
    }
    ~MyObject() {
        std::cout << "MyObject(" << data << ") жойылды\n";
    }
};

int main() {
    std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(10);
    // қатты есептегіш: 1, әлсіз есептегіш: 0

    {
        std::shared_ptr<MyObject> ptr2 = ptr1;
        // қатты есептегіш: 2, әлсіз есептегіш: 0

        std::weak_ptr<MyObject> weak_ptr = ptr1;
        // қатты есептегіш: 2, әлсіз есептегіш: 1

        if (auto locked_ptr = weak_ptr.lock()) {
            // қатты есептегіш: 3, әлсіз есептегіш: 1 (уақытша lock кезінде)
            std::cout << "Объект дерегі: " << locked_ptr->data << std::endl;
        }
        // қатты есептегіш: 2, әлсіз есептегіш: 1
    } // ptr2 аймағынан шығады
    // қатты есептегіш: 1, әлсіз есептегіш: 1

    // Объект әлі жойылмаған, себебі қатты есептегіш == 1

    {
        std::weak_ptr<MyObject> weak_ptr2 = ptr1;
        // қатты есептегіш: 1, әлсіз есептегіш: 2
    } // weak_ptr2 аймағынан шығады
    // қатты есептегіш: 1, әлсіз есептегіш: 1

} // ptr1 аймағынан шығады
// қатты есептегіш: 0, әлсіз есептегіш: 1
// Объект жойылады, себебі қатты есептегіш 0-ге айналды
// Басқару блогы әлсіз есептегіш 0-ге айналғанша қалады