Sobes.tech
Middle

როგორ მუშაობს std::shared_ptr-ში მიმთითებლის გამოთვლილი რაოდენობა?

sobes.tech AI

პასუხი AI-სგან

std::shared_ptr-ის მითითებების გამრიცხველობა ინახება ცალკეულ ობიექტში — მართვის ბლოკში (control block).

ამ მართვის ბლოკი შეიქმნება:

  • როდესაც პირველად შეიქმნება std::shared_ptr მითითებიდან.
  • როდესაც std::shared_ptr შექმნილია მომხმარებლის მიერ განსაზღვრული წაშლელის ან ალოკატორის გამოყენებით.
  • როდესაც გამოიყენება std::make_shared ან std::allocate_shared.

ამ მართვის ბლოკში შედის მინიმუმ ორი გამრიცხველობა:

  1. მტკიცე მითითებების გამრიცხველობა (strong count): იზრდება std::shared_ptr-ის შექმნის ან კოპირებისას, მცირდება განადგურებისას. როდესაც ეს გამრიცხველობა მიაღწევს ნულს, მართული ობიექტი გათავისუფლდება.
  2. სუსტი მითითებების გამრიცხველობა (weak count): იზრდება std::weak_ptr-ის შექმნისას std::shared_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