【发布时间】:2017-02-09 11:30:59
【问题描述】:
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中来实例化仍然使用分配器的子对象。反之则更难。 - 无论如何,内存分配是一项工作量相对较大的任务。相对而言,单个虚函数调用不会增加太多开销。
对于如何有效使用新的库功能,是否已有任何建议?
【问题讨论】:
-
分配器接口实际上并不难实现。 C++11 让它变得简单多了。您需要两个类型名称、两个函数和两个比较。
-
内存分配是否“相对工作密集”取决于分配器,不是吗?如果它从本地堆栈上的单调竞技场进行分配,它可能不会非常昂贵并且非常内联。
-
@KerrekSB 是的。实际上,如果没有 C++11 提供的适配器,我从来没有实现过它。不过,这不是我认为的优雅。
标签: c++ memory-management c++17 allocator