如何根据STL列表中的元素数量分配内存

How to allocate memory based on the number of elements in an STL list?

本文关键字:元素 分配 内存 何根 STL 列表      更新时间:2023-10-16

有一个选项可以为STL容器提供自定义分配器。然而,我找不到一种实现可以在内存池空间用完后增加内存池块大小。STL分配器如何读取列表容器的大小并自行增长块大小?

例如,块大小从1、2、4开始,依此类推,然后当容器内有1、3、7个节点时,块大小在下一次插入后立即增长。

标准容器使用提供的分配器(调用其成员函数)来分配所需的内存。相反的情况并没有发生——按照标准的规定,分配器接口中没有任何东西可以让它获得关于使用它的容器的信息。这意味着,任何自定义分配器——只要它具有与标准要求相同的接口——都无法询问容器大小。

要执行您想要的操作,您需要一个与标准分配器具有不同接口的专用分配器,以及一个知道如何与该专用分配器通信的自定义容器(例如std::list的替代品)。试图让自定义分配器与标准容器一起工作,或者让自定义容器与标准分配器一起工作,都不会很好地工作——接口是不兼容的。

此外,您描述的行为(每次分配加倍)是特定于标准库的实现的。尽管这种分配策略有些常见,但标准并不要求这样做。其他实现是允许的,有些实现确实使用了不同的分配策略。

最后,计算/估计容器大小的上限可能会更容易,用它来计算程序需要运行多少内存,并至少安装那么多内存。

分配器通常不依赖于作为其客户端的容器类型——这将是一个循环依赖。这个循环需要通过某种不完整的类接口或类型擦除来解决。

例如,使用不完整的类指针:

struct my_pool;
template< typename t >
struct my_allocator {
my_pool * pool;
// allocate, deallocate, etc.
};
struct my_pool {
std::list< foo, my_allocator< foo > > const * client;
};
std::list< foo, my_allocator< foo > > things;
my_pool.client = & things;

在这种情况下,my_pool依赖std::list<…, my_allocator>依赖my_allocator<std::__list_node>依赖my_pool,但循环是可以的,因为几个依赖关系只是指针。

例如,使用std::function类型擦除:

struct my_pool {
std::function< std::size_t() > client_size;
};
std::list< foo, my_allocator< foo > > things;
my_pool.client_size = [&]{ return things.size(); };

这个池甚至不需要知道容器类型。

但是,无论哪种情况,这似乎都不是特别好的设计。该池不能由其他容器共享,至少不能平等共享。