C ++ allocators_trait :: construct:动机,忽略的权衡

时间:2016-01-16 00:08:42

标签: c++ allocation c++-standard-library

我正在努力解决由std::allocator_traits::construct引起的一些痛苦。为了使容器成为符合要求的容器。作为分配器概念的用户,它需要使用construct而不是使用new来构造对象。这对我来说非常棘手。目前我有一个类(A类),它被设计为可以识别分配器,并且在某些时候它需要在分配的内存中创建另一个类(B类)的另一个实例。问题是B类实现了新对象的构造。如果我可以使用placement new,这不会成为一个问题:A将处理分配,将B传递给内存地址,B将构造为该。但是由于构造需要通过构造来执行,我需要将分配器类型注入到B中,模板化它,这会造成巨大的混乱。

我很认真地考虑使用placement new和静态断言我的分配器实例没有构造方法(注意静态构造函数调用实例方法,如果它存在,否则它会调用放置新的)。我从未感受到为分配器编写构造方法的最微小的冲动。制作这部分分配器概念的成本对我来说似乎很高;建设已经与分配纠缠在一起,分配者应该帮助分离它们。什么证明存在构造/破坏是正确的?深入了解设计决策,真实(非玩具)用例的例子,或者选择简单地使用新位置的重要性的想法。

有一个类似的问题; std::allocator construct/destroy vs. placement new/p->~T()。很久以前就问过这个问题,而且我没有在那里找到答案就足够了。作为用例,日志记录有点陈旧,即便如此:为什么分配器记录对象的实际构造?它可以记录分配和解除分配中的分配和解除分配,它没有在以下意义上回答问题:为什么构建首先成为分配器的一个省?我希望能找到更好的答案;它已经有好几年了,而且自那时以来分配器的变化很大(例如,分配器自11年以来就是有状态的)。

1 个答案:

答案 0 :(得分:2)

几点:

  • 确实没有std容器概念。标准中的容器需求表用于记录标准指定的容器。

  • 如果您有一个想要与std::allocator_traits<Alloc>交互的容器,您所要做的就是假设Alloc符合最低C ++ 11分配器要求并通过它与之交互std::allocator_traits<Alloc>

  • 禁止呼叫std::allocator_traits<Alloc>::construct,因为它可能不存在。

  • 标准指定的容器只需要为Alloc::construct调用std::allocator_traits<Alloc>::construct,并且禁止在容器可能需要构建的任何其他类型上使用container::value_type(例如内部节点)。

为什么std::allocator_traits<Alloc>::construct包含在&#34;分配器概念&#34;回到C ++ 98?

可能是因为当时的委员会觉得这样可以轻松处理x86远近指针 - 这个问题今天已不复存在。

话虽如此,construct是自定义std::scoped_allocator_adaptorconstruct的分配器的现实世界示例。有关这些自定义的详细说明,我向您指出最新的C ++ 1z工作草案N4567。规范并不简单,这就是为什么我不想在这里重现它。