给定一个非无状态自定义分配器A
(比如,竞技场分配器,绑定到运行时已知大小的某个连续内存块)和类S
,包含AllocatorAwareContainer的文件类型:
struct S
{
A() = default;
// another c-tors
std::vector< T > v;
std::shared_ptr< U > s;
};
我想将A
用于类S
的子集(甚至是所有) AllocatorAwareContainer 字段。很明显,我应该为类S
提供另一个模板参数,并相应地更改所有有趣数据成员的类型,如下所示:
template< typename A = std::allocator< void > >
struct S
{
// c-tors
template< typename X >
using allocator = typename std::allocator_traits< A >::template rebind< X >::other;
std::vector< T, allocator< T > > v;
std::shared_ptr< U, allocator< U > > s;
};
当前构造函数和其他构造函数的变化(假设A
不是 DefaultConstructible ,并且可能存在任何其他可能的限制)我应该做什么?
我应该将分配器A
存储在课程S
的其他字段中吗?
为类使用自定义分配器有哪些一般提示?
答案 0 :(得分:1)
我习惯使用来自bsl
的容器,它们是分配器感知的,并且用于创建分配器感知类。标准容器及其分配器使用的主要区别是bsl
使用指向分配器基类(bslma::Allocator
)的指针。这种方法很好地摆脱了std::rebind
- 舞蹈,这使得已经相对复杂的领域的问题变得复杂。否则,我认为这些概念可以转化。我没有使用带有标准库容器的分配器的经验。
使用分配器有两个基本规则,这些规则在实践中运作良好:
第二条规则意味着类的构造者需要照顾其所有成员。在已知成员类型的情况下,确定是否需要分配器以及如何构造分配器是相当直接的。当成员类型以某种形式是通用的,即它依赖于某种形式的模板参数时,通常不知道是否需要分配器。
当不清楚成员是否需要接收分配器时,使用bsl
时使用的方法是保持包裹成员。更具体地说,成员将持有bslalg::ConstructorProxy<T>
,其将静态地确定T
支持构造函数采用分配器和适当的传递分配器与否。