0

我试图了解boost::make_shared由 aboost::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()调用的三个参数是什么)

4

1 回答 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当前未初始化并且是删除器的一部分

    //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 个参数,因为这是make_shared.

    //Not sure
    pd->set_initialized();

这是删除器中的一个内部标志,它让它知道T已经构造了(这样当删除器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 );

这实际上创建了一个 new boost::shared_ptr,它使用与 相同的引用计数区域pt,但其get()和相关方法将返回pt2,这是指向 的指针T,存储在删除器中。

于 2014-06-08T01:02:25.303 回答