我想写一个自定义的内存管理器/分配器来学习。我很想拥有一个主分配器,它从堆中请求 n 个字节的 ram(通过 new)。接下来是几个分配器……适配器?每个都将与 master 接口(interface),请求一个内存块来管理,这些将是堆栈、线性、池、slab 分配器等,每个分配器管理来自它们的 master 池分配器的分配。
我遇到的问题是我是否应该编写自定义 allocator_traits 来与各种 STL 容器进行交互;或者如果我应该忽略适配器的想法并简单地重载 new 和 delete 以使用自定义池分配器/管理器,主要的。
我有兴趣了解的是,为 STL 容器提供单独的分配器会给我带来哪些切实的好处?似乎默认的 std::allocator 会根据需要调用 new 和 delete,所以如果我重载它们而不是从我的大自定义内存池请求,我将获得所有好处,而无需自定义 std::allocator 代码。
或者这是某些类型的分配器模型的问题,比如对 std::deque 使用堆栈分配器会比默认分配器工作得更好吗?如果是这样,正常的 STL 实现是否已经为各种容器类型专门化了默认分配器,或者在对默认分配器的调用中进行了优化?
如果这很重要,我正在通过 GCC 10+ 使用 C++20
最佳答案
如果你想替换全局分配器,包括你正在使用的每个库,你不必使用 std::allocator
。
std 分配器可让您执行诸如创建临时分配池之类的操作。假设您有一些可以保证不会超过某个范围的数据结构,并且您知道(无论分配什么)90% 以上的部分将保留分配到范围的末尾。
一个相对简单的 std 分配器可以分发内存,从不回收它,并在范围末尾清理它,这比任何全局 new
或 delete
运算符都快得多.
只要您对容器的内容和生命周期模式有特殊了解,就可以为该特定容器手动调整分配器。标准分配器不能。有时当您愿意做出 std 容器不愿意做出的妥协时,您可以使用自定义分配器修补它们的行为。
std::deque
无法有效地使用堆栈分配器,因为它无法假定您主要将其用作堆栈。您可能主要将其用作队列。当你主要将它用作队列时,堆栈分配器将是一场灾难;但是如果你将它 90%+ 用作堆栈,堆栈分配器可以以适度的内存开销为代价更快(如果 99%+,堆栈分配器可以处理异常情况并清理非基于堆栈的操作).
最后,分配器可以让您区分不同类型的容器。您可能希望将文档(持久性)状态的内存分配到一个内存区域,并将“临时”非持久性数据分配到其他地方。
是的,您应该考虑不要使用标准分配器。优化是可替代的,在使系统的其余部分更高效和更实用后,您可以调整低级内存分配。只有当你有一些东西可以工作,但速度不够快,并且你已经确定新/删除是你无法设计的基本瓶颈时,你应该说“好的,是时候更换分配了!”
关于c++ - 当我只能覆盖新的和删除的时候,为什么我要为 STL 容器编写自定义分配器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64619312/