Как удаляется контрольный блок у std::shared_ptr()?

Рейтинг: 0Ответов: 2Опубликовано: 19.02.2025

Есть момент который я не очень понимаю.

Если я не ошибаюсь то, при работе с std::weak_ptr() имеет значение, как мы создали std::shared_ptr().

   auto sp1 = std::shared_ptr<int>(new int(10));   // 1
   auto sp2 = std::make_shared<int>(10);           // 2

Разница между 1 и 2 в выделение памяти для объекта и контрольного блока(раздельно или вместе). Когда мы работаем с std::weak_ptr() мы можем проверить его на "просроченность" и даже если счетчик сильных ссылок = 0, то пока есть сам std::weak_ptr() будет существовать контрольный блок и вот я наконец подошел к вопросу!

Когда мы выделили память через std::make_shared<>(), затем у нас остался только сам weak_ptr получается у нас есть контрольный блок, но т.к. мы выделили память вместе то и объект вроде как бы есть, так что творится с этим объектом или выделенной памятью?

Ответы

▲ 1Принят

Контрольный блок в действительности - это возможная реализация поведения.

Все , что гарантируется - это при копировании shared_ptr указателя use_count() "откуда-то" берет значение счетчика использования увеличенное на единицу используя атомарное чтение (скорее всего с memory_order_relaxed). Нужно еще не забывать, что shared_ptr на вход получает еще и манипулятор удаления, который может быть вызван конструкторе, если в конструкторе произошло исключение. При удалении указателя shared_ptr уменьшает это значение на единицу и удаляет указатель с помощью заданного манипулятора удаления.

Т.е. объект УЖЕ может существовать при нулевом счетчика и ЕЩЕ может существовать в момент его обнуления. weak_ptr считывает значение того же счетчика, и если оно нулевое, считает, что указатель эквивалентен nullptr. Таким образом гарантируется достаточная корректность значения weak_ptr.

Контрольный блок - это некая структура, связывающая значение счетчика с указателем. Счетчик уже должен быть корректным во время создания указываемого объекта при конструировании shared_ptr и ЕЩЕ обязан существовать при удалении последней копии weak_ptr, и это все, что нас должно волновать.

▲ 2

Деструктор объекта в любом случае зовется когда умирает последний shared_ptr, но это не обязательно совпадает с освобождением его памяти.

Если использовали make_shared, то память под объект (+ контрольный блок) остается выделенной, пока не удалят контрольный блок.