Проанализируйте код на C++ с умными указателями: shared_ptr a = make_shared(); weak_ptr b = a; a.reset(); — что произойдёт с управлением ресурсом и как избежать цикла ссылок
Коротко и по делу. Что происходит в данном коде: - `shared_ptr a = make_shared();` — создаётся объект и control block; сильный счётчик (количество `shared_ptr`) становится use_count=1use\_count = 1use_count=1. - `weak_ptr b = a;` — `b` не увеличивает сильный счётчик, он увеличивает только счётчик слабых ссылок (control block остаётся). - `a.reset();` — уменьшается сильный счётчик до use_count=0use\_count = 0use_count=0. При этом ресурс (целевой объект `T`) уничтожается немедленно, потому что сильных ссылок больше нет. Control block будет уничтожен лишь когда все `weak_ptr` тоже исчезнут (т.е. когда счётчик слабых ссылок станет 000). Как проверить/получить объект из `weak_ptr`: - `auto s = b.lock();` — вернёт пустой `shared_ptr`, если объект уже уничтожен. - `b.expired()` — можно проверить, истёк ли объект. Как избежать циклов ссылок (главная причина утечек при `shared_ptr`): - В цикле из `shared_ptr` (A -> B и B -> A как `shared_ptr`) сильные счётчики никогда не станут 000 и объекты не будут уничтожены. - Решение: сделать хотя бы одну ссылку слабой (`weak_ptr`) — обычно "родительская" или "обратная" ссылка делается `weak_ptr`. Пример (Node с двусторонней связью): ``` struct Node { std::shared_ptr next; // владеющая ссылка на следующий std::weak_ptr prev; // обратная ссылка — слабая, чтобы не создавать цикл }; ``` Дополнение: если используете `shared_from_this()` внутри объекта, создавайте объект через `make_shared` и наследуйтесь от `std::enable_shared_from_this`, иначе `shared_from_this()` некорректен.
Что происходит в данном коде:
- `shared_ptr a = make_shared();` — создаётся объект и control block; сильный счётчик (количество `shared_ptr`) становится use_count=1use\_count = 1use_count=1.
- `weak_ptr b = a;` — `b` не увеличивает сильный счётчик, он увеличивает только счётчик слабых ссылок (control block остаётся).
- `a.reset();` — уменьшается сильный счётчик до use_count=0use\_count = 0use_count=0. При этом ресурс (целевой объект `T`) уничтожается немедленно, потому что сильных ссылок больше нет. Control block будет уничтожен лишь когда все `weak_ptr` тоже исчезнут (т.е. когда счётчик слабых ссылок станет 000).
Как проверить/получить объект из `weak_ptr`:
- `auto s = b.lock();` — вернёт пустой `shared_ptr`, если объект уже уничтожен.
- `b.expired()` — можно проверить, истёк ли объект.
Как избежать циклов ссылок (главная причина утечек при `shared_ptr`):
- В цикле из `shared_ptr` (A -> B и B -> A как `shared_ptr`) сильные счётчики никогда не станут 000 и объекты не будут уничтожены.
- Решение: сделать хотя бы одну ссылку слабой (`weak_ptr`) — обычно "родительская" или "обратная" ссылка делается `weak_ptr`.
Пример (Node с двусторонней связью):
```
struct Node {
std::shared_ptr next; // владеющая ссылка на следующий
std::weak_ptr prev; // обратная ссылка — слабая, чтобы не создавать цикл
};
```
Дополнение: если используете `shared_from_this()` внутри объекта, создавайте объект через `make_shared` и наследуйтесь от `std::enable_shared_from_this`, иначе `shared_from_this()` некорректен.