Где boost :: make_shared размер выделения памяти для базового объекта и объекта подсчета ссылок?

0

Я пытаюсь понять, как boost::make_shared выполняет выделение памяти для объекта, управляемого boost::shared_ptr и объект подсчета ссылок (совместно используемый shared_ptr).

Функция make_shared начинает выполнение здесь:

template< class T, class A1, class A2, class A3 >
typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3 )
{
    //Seems to create the smart_ptr for the object
    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );

    //Not sure?
    boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );

    //Calculates the address at which the bulk-allocation begins
    void * pv = pd->address();

    //Allocates the memory at address pv?
    ::new( pv ) T(
        boost::detail::sp_forward<A1>( a1 ), 
        boost::detail::sp_forward<A2>( a2 ), 
        boost::detail::sp_forward<A3>( a3 )
        );

    //Not sure
    pd->set_initialized();

    //Not sure
    T * pt2 = static_cast< T* >( pv );

    //Not sure
    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    return boost::shared_ptr< T >( pt, pt2 );
}

Кто-нибудь сможет объяснить оставшиеся строки?

Я пытаюсь определить, где определяется размер распределения объемной памяти (объект, на который указывают, и объект подсчета ссылок shared_ptr)?

Что меня бросает, так это то, что вызов address(), по-видимому, не учитывает размер объекта T при распределении адреса для размещения.

(Я действительно не понимаю, какие три параметра AX входят в метод и передаются на вызов new() места размещения)

Теги:
boost
memory-management
shared-ptr
make-shared

1 ответ

4
Лучший ответ

Пусть берется линия за строкой

  boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );

Это создает общий указатель, но ключ здесь является делетером. BOOST_SP_MSD(T) - это макрос, который разрешает делетиру с достаточным пространством для ваших данных. Таким образом, блок подсчета ссылок общего указателя также содержит пространство для делетера, которое теперь включает в себя пространство для вашего T

    //Not sure?
    boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );

Это получает адрес отправителя из общего указателя. Это будет указывать на создателя, созданного выше.

    //Calculates the address at which the bulk-allocation begins
    void * pv = pd->address();

Это возвращает начальный адрес для типа T, который в настоящее время неинициализирован и является частью deleter

    //Allocates the memory at address pv?
    ::new( pv ) T(
        boost::detail::sp_forward<A1>( a1 ), 
        boost::detail::sp_forward<A2>( a2 ), 
        boost::detail::sp_forward<A3>( a3 )
        );

Это новое место размещения. Это создает ваш T по адресу, указанному в pv. Он передает 3 аргумента, потому что это 3-arg версия make_shared.

    //Not sure
    pd->set_initialized();

Это внутренний флаг в deleter, который позволяет ему знать, что T был сконструирован (так что, когда вызывается operator() deleter operator(), он уничтожит его)

    //Not sure
    T * pt2 = static_cast< T* >( pv );

Это отличает void * выше в T*. Честно говоря, я не уверен, почему они просто не сохранили результат размещения нового.

    //Not sure
    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );

Это необходимо для обеспечения возможности enable_shared_from_this. Эта внутренняя функция устанавливает базовый механизм для enable_shared_from_this. Обычно это называется, когда вы помещаете что-то в shared_ptr

    return boost::shared_ptr< T >( pt, pt2 );

Это фактически создает новый boost::shared_ptr который использует ту же область подсчета ссылок, что и pt, но его методы get() и связанные с ним методы возвращают pt2, который является указателем на T, который хранится в deleter.

  • 0
    Буду ли я прав, думая, что объект подсчета ссылок находится перед объектом в памяти с более низким адресом?
  • 0
    @ user997112: Не знаю, но думаю, что да. Полагаться на какое-либо конкретное размещение кажется неразумным.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню