std::allocator 是空壳,仅提供统一接口;自定义 allocator 必须实现 allocate/deallocate/construct/destroy 及必要 typedef 和 rebind;不适用于 std::string 或 std::function;真正难点在于异常安全、移动语义与多线程稳定性。

std::allocator 是个空壳,别指望它帮你做内存优化
标准库里的 std::allocator 几乎不干实事——它底层调用 ::operator new 和 ::operator delete,和你直接 new/delete 没本质区别。它存在的主要意义是提供统一接口,让容器(比如 std::vector、std::list)能解耦具体分配逻辑。想靠换掉它来“提升性能”,大概率白忙活。
自定义 allocator 必须实现那几个关键成员函数
只要缺了 allocate、deallocate、construct、destroy,或者没正确定义 value_type、pointer、size_type 这些 typedef,编译器就会报错,常见错误信息像:no type named 'pointer' in 'MyAlloc<int>'</int> 或 no matching function for call to 'MyAlloc<int>::construct'</int>。
实操建议:
-
allocate里别直接用malloc,得用::operator new(或std::aligned_alloc如果要对齐) -
deallocate必须和allocate配对:用new分配的,必须用delete;用aligned_alloc的,得用free -
construct和destroy不再是“调用构造/析构函数”那么简单——C++17 起必须用std::allocator_traits委托,自己手写容易漏掉is_nothrow_constructible等约束
std::vector> 编译失败?检查模板参数推导和 rebind
很多自定义 allocator 在 std::vector 里一用就崩,不是因为 MyAlloc<int></int> 写错了,而是容器内部需要把 MyAlloc<int></int> “转成” MyAlloc<:vector>::node_type></:vector> 这类类型——这靠的是 rebind。C++11 以前靠嵌套 template <class u> struct rebind</class>,C++17 后改用 using rebind_alloc = MyAlloc<u>;</u>。
立即学习“C++免费学习笔记(深入)”;
典型现象:
- Clang 报
no member named 'rebind' in 'MyAlloc<int>'</int> - GCC 提示
invalid use of incomplete type 'MyAlloc<:vector>::node_type>'</:vector> - 即使加了
rebind,也得确保它是个 public、可访问的模板别名或结构体
别在生产代码里给 std::string 或 std::function 换 allocator
std::string 的 SSO(短字符串优化)会让 allocator 形同虚设——小字符串根本不动堆;std::function 内部存储策略复杂,自定义 allocator 很可能被忽略,甚至触发未定义行为。更现实的使用场景只有:固定大小对象池(如游戏实体)、NUMA 架构下的节点本地分配、或嵌入式中预分配的内存块。
还要注意:
- 所有使用该 allocator 的容器,必须用相同实例(或满足
==比较为 true),否则std::vector::swap或移动构造可能出问题 -
std::allocator_traits::propagate_on_container_swap和propagate_on_container_move_assignment默认是false,意味着移动/交换时不会传递 allocator 实例,这点极易被忽略
真正难的不是写出来,是让它在 move、swap、异常路径、多线程下都稳住——大部分自定义 allocator 只在单线程、无异常、不 swap 的玩具例子里跑得通。










