На каква основа няколко обекта 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 сочат към един и същ контролен блок, който следи броя на притежаваните негови копия и определя момента на освобождаване на управлявания ресурс.