c++ - boost::make_shared 底层对象和引用计数对象的内存分配大小在哪里?

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

我想了解 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) 是一个宏,它解析为一个删除器,为您的数据提供足够的额外空间。所以共享指针引用计数 block 还包括删除器的空间,现在包括你的 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();

这是删除器的一个内部标志,让删除器知道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 );

这实际上创建了一个新的 boost::shared_ptr,它使用与 pt 相同的引用计数区域,但它的 get() 和相关方法会返回pt2,也就是指向T的指针,存放在deleter中。

关于c++ - boost::make_shared 底层对象和引用计数对象的内存分配大小在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24101924/

相关文章:

c++ - 加载共享库时出错 : libcaffe. 所以

c++ - 将优化的埃拉托色尼筛从 Python 移植到 C++

c++ - 指针在删除它并在 C++ 中再次分配新内存后是否获得相同的内存地址?

c++ - boost asio - 套接字类的内存管理

C++ 枚举模板偏特化

c++ - 为什么 std::distance 会出现在 STL map 中?

c - 中止陷阱 :6 for fopen

c - C如何保护指针内存?

c++ - visual studio(ms编译器)如何知道它需要特定的boost库

c++ - boost 返回 0 的 CPU 时间