STD::ALLOCATE_SHARED使用什么类型来分配内存?
发件人https://en.cppreference.com/w/cpp/memory/shared_ptr/allocate_shared:
然后使用哪种类型来分配上述存储?换句话说,分配器要求之一存储空间通常大于template< class T, class Alloc, class... Args > shared_ptr<T> allocate_shared( const Alloc& alloc, Args&&... args );
sizeof(T)
,以便为共享指针的控制块和T
对象使用一个分配。..。所有内存分配都使用alloc
的副本完成,该副本必须满足Allocator要求。
Alloc::value_type
应该是什么?
解决方案
实际使用的类型取决于实现。根据Allocator要求,借助std::allocator_traits
特征类模板,可以通过std::allocator_traits<A>::rebind_alloc<T>
机制将任何分配器rebind
赋给其他类型。
假设您有一个分配器
template<class T>
class MyAlloc { ... };
如果您写:
std::allocate_shared<T>(MyAlloc<T>{});
这并不意味着将使用MyAlloc<T>
执行分配。如果在内部需要分配另一种类型的对象S
,我们可以通过
std::allocator_traits<MyAlloc<T>>::rebind_alloc<S>
它的定义是,如果MyAlloc
本身没有提供rebind<U>::other
成员类型别名,则使用默认实现,该实现返回MyAlloc<S>
。分配器对象是通过相应的MyAlloc<S>
的转换构造函数(请参阅分配器要求)从传递给std::allocate_shared()
(此处为MyAlloc<T>{}
)的对象构造的。
让我们来看看一些特殊的implementation-libstdc++。对于上面的行,实际分配由
执行MyAlloc<std::_Sp_counted_ptr_inplace<T, Alloc<T>, (__gnu_cxx::_Lock_policy)2>
这是合理的:std::allocate_shared()
为同时包含T
和控制块的对象分配内存。_Sp_counted_ptr_inplace<T, ...>
就是这样一个对象。它在_M_storage
数据成员中包含T
内部:
__gnu_cxx::__aligned_buffer<T> _M_storage;
许多其他地方也使用相同的机制。例如,std::list<T, Alloc>
使用它来获取分配器,然后使用该分配器来分配列表节点,除了T
之外,列表节点还保存指向其邻居的指针。
一个有趣的相关问题是,为什么分配器不是模板模板参数,这似乎是一个自然的选择。已讨论here。
相关文章