Проанализируйте фрагмент на C++: std::shared_ptr p(new A); std::shared_ptr q = p; p.reset(); — каким будет жизненный цикл объекта A, и какие проблемы могут возникнуть при циклических ссылках?
Кратко и по шагам. Жизненный цикл в данном фрагменте: - При выполнении `std::shared_ptr p(new A);` создаётся объект `A` и сопутствующий control block; счётчик ссылок равен 111. - После `std::shared_ptr q = p;` оба `shared_ptr` делят ownership, счётчик увеличивается до 222. - При `p.reset();` `p` отпускает владение, счётчик уменьшается до 111. Объект `A` не удаляется, т.к. остаётся `q`. - Объект `A` будет уничтожен только когда последний `shared_ptr` (здесь `q`) сбросит владение и счётчик упадёт до 000. Проблема циклических ссылок: - Если объекты содержат `shared_ptr`, образующие цикл (например `A` держит `shared_ptr`, а `B` держит `shared_ptr`), счётчики в цикле никогда не станут 000. В результате памяти утечёт (движок не удалит объекты). - Решение: разорвать цикл с помощью `std::weak_ptr`, который не увеличивает счётчик ссылок. Обычно одну сторону цикла делают `weak_ptr`, чтобы при отсутствии внешних владений счётчики упали до 000 и объекты уничтожились. Дополнительно (коротко): - Рекомендуется использовать `std::make_shared()` вместо `shared_ptr(new A)` для эффективности и безопасности. - Нельзя создавать несколько `shared_ptr` из одного сыроого указателя отдельно — это приведёт к двойному удалению.
Жизненный цикл в данном фрагменте:
- При выполнении `std::shared_ptr p(new A);` создаётся объект `A` и сопутствующий control block; счётчик ссылок равен 111.
- После `std::shared_ptr q = p;` оба `shared_ptr` делят ownership, счётчик увеличивается до 222.
- При `p.reset();` `p` отпускает владение, счётчик уменьшается до 111. Объект `A` не удаляется, т.к. остаётся `q`.
- Объект `A` будет уничтожен только когда последний `shared_ptr` (здесь `q`) сбросит владение и счётчик упадёт до 000.
Проблема циклических ссылок:
- Если объекты содержат `shared_ptr`, образующие цикл (например `A` держит `shared_ptr`, а `B` держит `shared_ptr`), счётчики в цикле никогда не станут 000. В результате памяти утечёт (движок не удалит объекты).
- Решение: разорвать цикл с помощью `std::weak_ptr`, который не увеличивает счётчик ссылок. Обычно одну сторону цикла делают `weak_ptr`, чтобы при отсутствии внешних владений счётчики упали до 000 и объекты уничтожились.
Дополнительно (коротко):
- Рекомендуется использовать `std::make_shared()` вместо `shared_ptr(new A)` для эффективности и безопасности.
- Нельзя создавать несколько `shared_ptr` из одного сыроого указателя отдельно — это приведёт к двойному удалению.