首页 > 解决方案 > 如何正确使用 C++11 风格的内存池?

问题描述

我正在尝试设计一个简单的嵌入式应用程序的内部机制。数据块到达网络,需要传送到由寻址机制确定的组件。多个组件可以订阅同一个地址。我想设计一个架构,其中传入的块被封装到从内存池分配的包装对象中。只要需要,每个组件都可以保留包装器(以及其中的数据),并且在所有组件释放它时应该将其释放。那时它会返回到池中并再次准备好分配。游泳池耗尽不是一个问题。

我打算使用这个满足分配器的内存池实现。对于我计划使用的包装器对象的自动销毁,std::shared_ptr因此当所有组件释放包装器时,它会自动销毁并且使用的内存返回到池中。

我没有看到这两个概念如何结合在一起。如果我直接从池中分配内存(通过调用allocate()),它会给我一个指向数据块的指针,这很好,但是如何deallocate()自动调用呢?或者我是否需要为我的包装对象使用另一个容器,例如std::list并将其传递给内存池分配器?

标签: c++c++11memory-managementsmart-pointersmemory-pool

解决方案


您可以使用std::shared_ptr自定义分配器使用std::allocate_shared. 无论如何,这可能是您想要的,因为我假设您也希望使用池分配器来分配控制块(即引用计数)。

使用 构造对象std::allocate_shared时,分配器的副本存储在 中shared_ptr,因此deallocate()将在销毁时调用正确的。

请注意,您还可以std::shared_ptr使用自定义删除器创建您的,例如:

auto allocator = getAllocator<Foo>();
auto ptr = std::shared_ptr<Foo>(new(allocator.allocate()) Foo,
  [&allocator](auto * ptr) { allocator.deallocate(ptr); });

但是,正如我所提到的,这可能不是您想要的,因为引用计数的空间不会使用您的分配器对象分配。

顺便说一句,如果你还在“货比三家”,这里有另一个我非常喜欢的内存池实现:foonathan::memory。它提供了自己的allocate_shared.


推荐阅读