一、allocator 是什么?
分配器 = 封装了"内存分配/释放" + "对象构造/销毁" 的类模板
标准库容器(vector、list、map 等)都用它管理内存,默认是 std::allocator<T>。
二、为什么需要 allocator?
直接 new/delete 的问题
cpp
// new 做了两件事,绑定在一起:
T* p = new T(); // ① 分配内存 + ② 构造对象
delete p; // ① 析构对象 + ② 释放内存
问题:有时只想分配内存,不想构造对象;或者想先构造,晚些释放。
allocator 把四步拆开
表格
| 操作 | 函数 | 含义 |
|---|---|---|
| 分配内存 | allocate(n) |
只分配 n 个对象的原始内存(未初始化) |
| 构造对象 | construct(p, args) |
在已分配的内存上构造对象 |
| 析构对象 | destroy(p) |
调用析构函数,不释放内存 |
| 释放内存 | deallocate(p, n) |
归还内存给系统 |
三、标准使用方式
cpp
#include <memory>
std::allocator<int> alloc; // 创建分配器
// 1. 分配内存:10 个 int 的空间,未初始化
int* p = alloc.allocate(10);
// 2. 构造对象:在 p[0] 位置构造一个 int = 42
alloc.construct(p, 42); // C++17 前
// 或
std::allocator_traits<decltype(alloc)>::construct(alloc, p, 42);
// 3. 使用对象
std::cout << *p; // 42
// 4. 析构对象:只销毁,内存还在
alloc.destroy(p); // C++17 前
// 5. 释放内存:归还 10 个 int 的空间
alloc.deallocate(p, 10);
四、C++17 的变化
C++17 起 construct/destroy 被标记为废弃 ,推荐用 allocator_traits 或直接 std::construct_at:
cpp
#include <memory>
std::allocator<int> alloc;
int* p = alloc.allocate(1);
// C++17 推荐方式:
std::construct_at(p, 42); // 构造
std::destroy_at(p); // 析构
alloc.deallocate(p, 1);
五、自定义 allocator(实战)
场景:跟踪内存分配、使用内存池
cpp
template <typename T>
class TrackingAllocator {
public:
using value_type = T;
TrackingAllocator() = default;
template <typename U>
TrackingAllocator(const TrackingAllocator<U>&) {}
// 分配内存
T* allocate(std::size_t n) {
std::size_t bytes = n * sizeof(T);
std::cout << "分配 " << bytes << " 字节\n";
return static_cast<T*>(::operator new(bytes));
}
// 释放内存
void deallocate(T* p, std::size_t n) {
std::cout << "释放 " << n * sizeof(T) << " 字节\n";
::operator delete(p);
}
};
// 使用自定义分配器的容器
std::vector<int, TrackingAllocator<int>> vec;
vec.push_back(1); // 输出:分配 4 字节(或更多,vector 会预分配)
六、allocator 与容器的配合
cpp
// 标准 vector 的第二个模板参数就是 allocator
template <typename T, typename Allocator = std::allocator<T>>
class vector;
// 默认使用 std::allocator
std::vector<int> v1; // = std::vector<int, std::allocator<int>>
// 自定义 allocator
std::vector<int, TrackingAllocator<int>> v2;
七、一句话总结
| 问题 | 答案 |
|---|---|
| allocator 是什么? | 把"内存分配"和"对象构造"解耦的工具 |
| 为什么要用它? | 精细控制内存生命周期,支持自定义分配策略(内存池、跟踪等) |
| 谁在用? | 所有标准库容器默认都用 std::allocator |
| 现代 C++ 注意? | C++17 起 construct/destroy 废弃,用 std::construct_at/destroy_at |