Может ли генерировать класс из "enable_shared_from_this" повысить производительность?
make_shared
более эффективен, чем отдельный вызов new
и создает shared_ptr
, потому что make_shared
выделяет пространство для подсчета ссылок и слабого подсчета в том же блоке памяти, что и экземпляр объекта клиента (эффективно давая shared_ptr
большинство преимуществ производительности intrusive_ptr
).
enable_shared_from_this
дает общий указатель без ссылки на какой-либо общий указатель. Поэтому такие вещи, как ссылочный и слабый счет, должны быть как-то доступны изнутри клиентского объекта. Поэтому было бы разумно, чтобы enable_shared_from_this
вызывал интрузивный счет, похожий на make_shared
.
Однако я понятия не имею, как что-то подобное может быть реализовано (и я не уверен, что буду следить за тем, что происходит там, даже если я смотрю на фактический источник).
Будет ли смысл тогда (по соображениям производительности) отмечать мой класс enable_shared_from_this
, если я знаю, что он когда-либо будет использоваться как shared_ptr
и никогда не будет как необработанный объект?
Ответы
Ответ 1
Я никогда не врывался в детали реализации, но для shared_from_this
для работы объект уже должен управляться внешним shared_ptr
, поэтому он в какой-то мере не связан. То есть первый shared_ptr
мог быть создан с помощью make_shared
, и в этом случае счетчик и объект будут вместе (как вы говорите, назойливым указателем вроде), но это не обязательно.
Мое первое предположение состоит в том, что enable_shared_from_this
добавляет эквивалент weak_ptr
, а не a shared_ptr
. EDIT: Я только что проверил реализацию в gcc4.6:
template <typename _Tp>
class enable_shared_from_this {
...
mutable weak_ptr<_Tp> _M_weak_this;
};
Ответ 2
Я так не верю. Реализация enable_shared_from_this
не строго определена, но пример реализации присутствует в стандарте, который соответствует тому, как это делается. В основном, есть скрытый weak_ptr
, который shared_ptr
и друзья имеют доступ к... в любое время a shared_ptr
предоставляется право собственности на объект, полученный из enable_shared_from_this
, он обновляет внутренний указатель. Тогда shared_from_this()
просто возвращает сильную версию этого слабого указателя.
В общем случае реализация не может предполагать, что никто никогда не перейдет shared_ptr(new T)
вместо использования make_shared
, поэтому назойливый счетчик ссылок будет рискован. Вы можете вместо этого сделать этот guarentee самостоятельно, любым способом, который вы используете для создания объектов в первую очередь.
Ответ 3
Boost enable_shared_from_this
не меняет реализацию самого shared_ptr
. Помните, что shared_ptr
сопряжен с weak_ptr
- это означает, что даже после удаления объекта данные отслеживания могут остаться вокруг, чтобы сообщить weak_ptr
, что объект мертв. Таким образом, он не может быть встроен в объект, даже с enable_shared_from_this
. Все enable_shared_from_this
действительно вставляет указатель на данные отслеживания в объект, поэтому shared_ptr
может быть сконструирован только с указателем на объект.
Вот почему intrusive_ptr
не может иметь вариант weak_intrusive_ptr
.