【问题标题】:Where does boost::make_shared size of memory allocation for underlying object and reference counting object?boost::make_shared 底层对象和引用计数对象的内存分配大小在哪里?
【发布时间】:2014-06-08 00:32:39
【问题描述】:

我试图了解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()调用)

【问题讨论】:

    标签: c++ memory-management boost shared-ptr make-shared


    【解决方案1】:

    让我们逐行看

      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 )
            );
    

    这是一个新的展示位置。这会在pv 中提供的地址构造您的T。它传递了 3 个参数,因为这是 make_shared 的 3-arg 版本。

        //Not sure
        pd->set_initialized();
    

    这是deleter中的一个内部标志,它让它知道T已经被构造(这样当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的指针,它被存储在删除器中。

    【讨论】:

    • 我认为引用计数对象放在内存中的对象之前,地址较低,我是否正确?
    • @user997112:我不知道,但我猜是的。依赖任何特定的位置似乎是不明智的。
    • 确实如此,因为如果您使用shared_ptr&lt;T&gt;(new T)make_shared&lt;T&gt;(),则展示位置可能会有所不同。这是一个实现细节,标准没有说明任何内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 2017-02-21
    • 2015-10-15
    • 2021-11-28
    相关资源
    最近更新 更多