🍪 Как выдать shared_ptr на себя из метода? — 2 июня 2026 г. в 19:28:02.909
🍪 Как выдать shared_ptr на себя из метода? std::shared_ptr хранит рядом с объектом control block — счётчик владельцев. Несколько shared_ptr безопасны, пока делят один control block. Проблема: иногда объекту нужно отдать shared_ptr на себя, но внутри метода есть только сырой this, который о counter'е ничего не знает. ❌ Наивный способ: struct S { std::shared_ptr<S> self() { return std::shared_ptr<S>(this); } }; auto p = std::make_shared<S>(); auto q = p->self(); У p и q свои control block'и, у каждого счётчик = 1 → объект удалится дважды (UB). ✅ Решение — enable_shared_from_this: struct S : std::enable_shared_from_this<S> { std::shared_ptr<S> self() { return shared_from_this(); } }; auto p = std::make_shared<S>(); auto q = p->self(); База добавляет скрытый weak_ptr<S>. При первом заворачивании в shared_ptr его конструктор замечает эту базу и кладёт туда свой control block. Теперь q разделяет счётчик с p. 🍴 Что делает shared_from_this(): shared_ptr<S> shared_from_this() { return shared_ptr<S>(weak_this); } Это конструктор из weak_ptr, а не lock(): без владельца он бросает bad_weak_ptr, а не молча возвращает пустой указатель. 🍙 Когда скрытый weak_ptr пуст: S s; // на стеке — никто не владеет s.shared_from_this(); // 💥 bad_weak_ptr (до C++17 — UB) struct T : std::enable_shared_from_this<T> { T() { shared_from_this(); } // 💥 хук срабатывает после конструктора }; Правила: наследовать публично, владеть через shared_ptr (лучше make_shared). Нужна проверка без исключения — в C++17 есть weak_from_this(): 🍉 Правила: • Наследуйте enable_shared_from_this публично. • Владейте объектом через shared_ptr — лучше make_shared (одна аллокация + exception-safety). • Не вызывайте shared_from_this() в конструкторе и на объектах со стека — будет bad_weak_ptr. • Нужна проверка без исключения — в C++17 берите weak_from_this(): if (auto sp = obj.weak_from_this().lock()) { /* владелец есть */ }

