Allocator是STL中封装内存分配逻辑的组件,可通过自定义实现如内存池等高效管理方式,满足特定场景需求。

在C++中,STL容器(如std::vector、std::list等)默认使用全局的::operator new和::operator delete来分配和释放内存。但你可以通过自定义Allocator来控制容器的内存管理方式,比如使用内存池、共享内存或栈内存等特殊场景。
什么是Allocator?
Allocator是STL中用于封装内存分配与释放逻辑的一个模板组件。每个STL容器都接受一个可选的Allocator模板参数。标准库提供了默认实现std::allocator,你也可以提供自己的版本。
一个合法的Allocator需要满足一定的接口要求,包括:
-
value_type:被分配类型的别名 -
allocate(size_t):分配原始内存 -
deallocate(pointer, size_t):释放内存 -
construct(pointer, args...):构造对象(C++17前) -
destroy(pointer):析构对象 -
rebind:允许为其他类型生成对应分配器(C++17后逐渐被移除)
实现一个简单的自定义Allocator
下面是一个简化但可用的自定义Allocator示例,它基于malloc和free进行内存管理,可用于std::vector:
立即学习“C++免费学习笔记(深入)”;
// my_allocator.h
include
include
template
MyAllocator() = default;
template zuojiankuohaophpcntypename Uyoujiankuohaophpcn
constexpr MyAllocator(const MyAllocatorzuojiankuohaophpcnUyoujiankuohaophpcn&) noexcept {}
T* allocate(std::size_t n) {
if (n == 0) return nullptr;
T* ptr = static_castzuojiankuohaophpcnT*youjiankuohaophpcn(std::malloc(n * sizeof(T)));
if (!ptr) throw std::bad_alloc();
return ptr;
}
void deallocate(T* ptr, std::size_t) noexcept {
std::free(ptr);
}
template zuojiankuohaophpcntypename U, typename... Argsyoujiankuohaophpcn
void construct(U* p, Args&&... args) {
::new(p) U(std::forwardzuojiankuohaophpcnArgsyoujiankuohaophpcn(args)...);
}
template zuojiankuohaophpcntypename Uyoujiankuohaophpcn
void destroy(U* p) {
p-youjiankuohaophpcn~U();
}};
// 必须提供这个,使不同类型的allocator能相互转换
template
template
在STL容器中使用自定义Allocator
将上面的分配器应用于std::vector非常简单:
#include "my_allocator.h"
include
include iostream>
int main() {
// 使用自定义分配器创建vector
std::vector
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
for (const auto& v : vec) {
std::cout zuojiankuohaophpcnzuojiankuohaophpcn v zuojiankuohaophpcnzuojiankuohaophpcn " ";
}
std::cout zuojiankuohaophpcnzuojiankuohaophpcn "\n";
return 0;}
输出结果为:10 20 30
虽然行为与默认分配器一致,但内存来自malloc/free而非new/delete,便于调试或集成特定系统调用。
高级用途:内存池Allocator
更实用的场景是实现一个内存池分配器,减少频繁调用系统分配带来的开销。
基本思路:
- 预分配一大块内存作为“池”
- 重写
allocate从池中切片返回 - 多个小对象复用同一块内存,提升性能
注意:完整内存池需处理对齐、碎片、回收策略等问题,这里只展示框架结构:
template
PoolAllocator() {
pool = reinterpret_castzuojiankuohaophpcnT*youjiankuohaophpcn(aligned_alloc(alignof(T), sizeof(T) * PoolSize));
}
~PoolAllocator() {
if (pool) std::free(pool);
}
T* allocate(size_t n) {
if (n != 1) throw std::bad_alloc(); // 简化:仅支持单个对象
for (size_t i = 0; i zuojiankuohaophpcn PoolSize; ++i) {
if (!used[i]) {
used[i] = true;
return &pool[i];
}
}
throw std::bad_alloc(); // 池满
}
void deallocate(T* p, size_t) noexcept {
size_t index = p - pool;
if (index zuojiankuohaophpcn PoolSize) used[index] = false;
}
// construct/destroy 同上...
template zuojiankuohaophpcntypename Uyoujiankuohaophpcn struct rebind { using other = PoolAllocatorzuojiankuohaophpcnU, PoolSizeyoujiankuohaophpcn; };};
这类分配器适合对象大小固定、生命周期短且频繁创建销毁的场景,如游戏开发中的粒子系统。
基本上就这些。自定义Allocator不复杂但容易忽略细节,尤其是对齐和异常安全。建议初学者先基于std::allocator继承或参考标准实现,逐步替换底层逻辑。实际项目中也可考虑Boost.Pool或Google tcmalloc等成熟方案。









