Я пытаюсь понять как 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::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
, который в настоящее время неинициализирован и является частью средства удаления
//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-аргументная версия make_shared
,
//Not sure
pd->set_initialized();
Это внутренний флаг в удалителе, который позволяет ему знать, что T
был построен (так что, когда удалитель operator()
называется, это его уничтожит)
//Not sure
T * pt2 = static_cast< T* >( pv );
Это бросает пустоту * выше в 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
, который хранится в удалителе.