新的C++代码应该使用内存资源而不是分配器吗?

33
C++17将为我们带来std::pmr::memory_resource,这是一个用于分配和释放内存的干净接口。与Allocator概念不同的是,它只做这一件事情,没有其他功能。还会有std::pmr::polymorphic_allocator,它将内存资源包装成经典分配器,以便与现有容器一起使用。
如果我要编写针对C++17及更高版本的新容器(或其他消耗大量内存的类型),我应该继续使用Allocator概念编程,还是直接使用更新、更干净的抽象呢?
截至目前,我的想法如下。 继续使用分配器的原因:
  • 它与标准库和现有代码保持一致。即使是新的std::pmr::*容器别名也继续使用分配器。
  • 由于内存资源可以被包装成std::pmr::polymorphic_allocator,因此分配器接口更加通用,满足更多客户的需求。
  • 内存资源始终使用运行时多态性,因此与分配器提供的零开销抽象相比,它们具有较小的额外运行时开销。
  • 也许实际上有人需要分配器接口的其他部分(例如自定义指针类型),这是纯内存资源无法提供的。

开始使用内存资源而不是分配器的原因:

  • 内存分配器接口不太方便实现。而std::pmr::memory_resource接口则更为简洁明了。
  • 由于内存资源是多态的,它们不会影响容器的类型,这意味着需要实例化的模板较少(因此可能编译更快、可执行文件更小),并且使我们能够将更多的代码移入单独的翻译单位。
  • 如果一个对象使用了内存资源,它总是可以实例化一个仍然使用分配器的子对象,方法是将内存资源包装到std::pmr::polymorphic_allocator中。反过来就比较困难。
  • 内存分配本身已经是相对耗时的任务了,单个虚函数调用并不会增加太多开销,相对而言。

是否已经存在如何有效使用新库特性的建议?


1
分配器接口实际上并不难实现。C++11使它变得更简单了。你只需要两个类型名、两个函数和两个比较就可以了。 - Kerrek SB
2
内存分配是否“相对工作密集”取决于分配器,不是吗?如果它从本地堆栈上的单调区域分配,那么它可能不会非常昂贵,并且可以很好地内联。 - Kerrek SB
@KerrekSB 这是真的。实际上,我从未在没有C++11提供的适配器的情况下实现过它。不过,这并不是我认为优雅的方式。 - 5gon12eder
1个回答

13

目前不行。

C++中的分配器比以前更容易使用了。

它们提供了pmr(多态)和经典分配器支持。

更重要的是,基于pmr的分配已经多年没有被广泛使用。任何弱点可能仍会暴露出来。

快速池化分配器,甚至固定缓冲区或sbo(小缓冲区优化)扩展,可能会注意到虚拟化开销。


然而,对于编写容器的人来说,使用多态字节分配器作为默认值是否有意义呢?在编译时选择分配器是有意义的,但对于通用目的来说,似乎pmr是一个合理的默认值。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接