Когда ~A()
и ~B()
работают, могу ли я быть уверенным, что хранилище, где жил C
, все еще присутствует?
Конечно! Было бы трудно использовать базовый класс, который пытается освободить свою собственную память (память, в которой он находится). Я не уверен, что это даже формально законно.
Реализации этого не делают: когда shared_ptr<T>
уничтожается или сбрасывается, счетчик ссылок (R C) для общего владельца T
уменьшается (атомарно); если оно достигло 0 в декременте, то начинается уничтожение / удаление T
.
Затем счетчик слабых владельцев или T-существует уменьшается (атомарно), так как T
больше не существует : нам нужно знать, являемся ли мы последней сущностью, заинтересованной в блоке управления; если декремент дал ненулевой результат, это означает, что существует некоторая weak_ptr
, которая разделяет (может быть 1 акция или 100%) владение контрольным блоком, и теперь они отвечают за освобождение.
В любом случае , коэффициент atomi c в какой-то момент будет иметь нулевое значение для последнего совладельца.
Здесь нет потоков, нет недетерминизма и, очевидно, последний weak_ptr<T>
был уничтожен при уничтожении C
. (Ваше неписанное предположение о том, что никакие другие weak_ptr<T>
не были сохранены.)
Разрушение всегда происходит в этом точном порядке. Блок управления используется для уничтожения, поскольку shared_ptr<T>
не знает (в общем), какой (потенциально не виртуальный) деструктор (потенциально отличающийся) наиболее производного класса для вызова . (Блок управления также знает , а не , чтобы освободить память на общем счетчике, достигнув нуля для make_shared
.)
Единственное практическое отличие между реализациями, похоже, заключается в мелких деталях ограждений памяти и избегая некоторых атоми c операций в обычных случаях.