Почему enable_shared_from_this встраивает слабый указатель вместо непосредственного встраивания счетчика ссылок? - PullRequest
10 голосов
/ 26 июля 2011

Помощник enable_shared_from_this содержит слабый указатель, который устанавливается при создании общего указателя на объект. Это означает, что существует счетчик ссылок (выделенный отдельно или вместе с объектом с использованием make_shared) и дополнительный weak_ptr в объекте.

Теперь, почему он просто не содержит счетчик ссылок? При установке shared_ptr из тупого указателя тип должен быть полностью определен, поэтому конструктор или оператор присваивания shared_ptr может определить тип, полученный из enable_shared_from_this, и использовать правильный счетчик, а формат может остаться прежним, поэтому копирование не волнует. Фактически, shared_ptr уже должен обнаружить его, чтобы установить встроенный weak_ptr.

Ответы [ 3 ]

7 голосов
/ 26 июля 2011

Первое, что приходит на ум, это то, будет ли такой подход вообще осуществимым, и ответ таков:

struct X : enable_shared_from_this {};
std::shared_ptr<X> p( new X );
std::weak_ptr<X> w( p );
p.reset();                      // this deletes the object
if ( w.use_count() ) {          // this needs access to the count object
                                //    but it is gone! Undefined Behavior

Если счет хранится в объекте, то weak_ptr не может пережить объект, что является нарушением договора. Вся идея weak_ptr состоит в том, что они могут пережить объект (если последний shared_ptr выходит из области видимости, объект удаляется, даже если есть weak_ptr)

1 голос
/ 26 июля 2011

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

1 голос
/ 26 июля 2011

Разделение задач: make_shared для встраивания счета, enable_shared_from_this для shared_from_this.

Нет причин смешивать эти два: библиотека не может предположить, что клиентский код имеет для требований. Разделяя их, клиентский код может выбирать то, что подходит лучше всего.

Кроме того, Boost (откуда взято shared_ptr) также предлагает intrusive_ptr.

(Учтите, что ваше предложение, по-видимому, не допускает пользовательских удалений. Вы могли бы исправить это, изменив enable_shared_from_this на template<typename T, typename Deleter = default_deleter<T>> class enable_shared_from_this;, но к этому моменту оно приближается к переизобретению intrusive_ptr. )

...