向量(容器)需要使用"allocator"吗?

Does a vector (container) need to use an "allocator"?

本文关键字:allocator 容器 向量      更新时间:2023-10-16

我正在研究如何创建自定义容器,例如eastl的容器和其他几个模型,我发现它们都使用了"分配器",就像std::vectorstd::allocator一样。这让我思考,当向量容器的新实现通常具有newdelete的底层内存管理覆盖时,为什么要使用分配器?

对于小程序来说,能够在程序级别替换operator new()operator delete()(及其数组版本)就足够了。如果你的程序由数百万行代码组成,运行许多不同的线程,这根本不合适。你经常想要甚至需要更好的控制。为了有效地使用自定义分配器,您还需要能够使用与外部分配器相同的对象来分配子对象。

例如,考虑在某种可能运行多个线程的服务器中回答请求时使用的内存竞技场。从operator new()获取内存可能相当昂贵,因为它涉及到分配锁和在越来越碎片化的堆中找到合适的内存块。为了避免这种情况,您只需要分配几个内存块(理想情况下只分配一个,但您可能事先不知道所需的大小),并将所有对象都放在那里。分配器可以做到这一点。要做到这一点,您需要向所有分配内存的实体通知该内存块,也就是说,您需要将分配器传递给所有可能分配内存的对象。如果你分配了一个std::vector<std::string, A>,那么std::string对象应该知道分配器:仅仅告诉std::vector<std::string, A>在哪里以及如何分配内存是不足以避免大多数内存分配的:你还需要告诉std::string(好吧,实际上是std::basic_string<char, std::char_traits<char>, B>,用于与A相关的合适的分配器类型B)。

也就是说,如果你真的想控制你的内存分配,你肯定想把分配器传给所有分配内存的东西。使用替换版本的全局内存管理工具可能会对您有所帮助,但这是相当有限的。如果您只想编写一个自定义容器,并且内存分配不是您关心的问题,那么您不一定需要麻烦。然而,在长时间运行的大型系统中,内存分配是众多问题之一。

分配器是定义标准库容器使用的内存模型的类。

每个标准库容器都有自己的默认分配器,但是容器的用户可以在默认分配器的基础上提供自己的分配器
这是为了增加灵活性
它确保用户可以提供自己的分配器,该分配器提供除常规堆之外的另一种形式的内存管理(例如:内存池)。

如果您想生成一个标准兼容的容器,那么答案当然是肯定的。。。分配器在标准中进行了描述,因此它们是必需的。

然而,根据我个人的经验,分配器并没有那么有用。。。因此,如果您正在开发一个特定用途的容器,以克服标准容器的一些结构限制,那么我建议您忘记分配器,除非您真的看到了使用它们的原因。

如果你开发一个容器只是因为你认为你可以比标准向量做得更好,那么我的猜测是你在浪费时间。我不喜欢分配器的想法设计(在类型上去掉一些不应该有的东西),但幸运的是,它们可以被忽略。当您不需要分配器(即总是)时,分配器唯一的烦恼可能是错误消息中的一些混乱。。不管怎样,那都是一团糟。