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