你不需要手写分配器——标准库给你了#
#include <memory_resource>
// 1. 分配一个缓冲区(可以栈上,可以堆上)
char buffer[1024 * 1024]; // 1MB
// 2. 创建 monotonic_buffer_resource(就是上面的 Arena)
std::pmr::monotonic_buffer_resource pool(buffer, sizeof(buffer));
// 3. 创建 pmr::vector,指定使用 pool
std::pmr::vector<int> vec(&pool);
vec.reserve(100000); // 从 pool 分配,不调用 malloc
// 4. pool 析构时自动释放整个 buffer
PMR 提供的三种 Resource#
| Resource |
行为 |
适用场景 |
monotonic_buffer_resource |
只加偏移,不释放单个对象,整块释放 |
同 Arena,几乎最快 |
unsynchronized_pool_resource |
对象池,管理不同大小的块,可释放单个 |
需要频繁 alloc/dealloc 相同大小的对象(单线程) |
synchronized_pool_resource |
同上,但线程安全 |
多线程共享同一个分配器 |
实战:用 PMR 优化日志处理#
// 场景:HTTP 请求处理,每次请求需要构建大量 string
// 每次请求结束后,这些 string 全部可以释放
struct RequestContext {
std::pmr::string method;
std::pmr::string path;
std::pmr::vector<std::pmr::string> headers;
std::pmr::string body;
// 所有 pmr::string 使用同一个 pool
explicit RequestContext(std::pmr::memory_resource* pool)
: method(pool), path(pool), headers(pool), body(pool) {}
};
// 每次请求创建一个 arena
char buffer[1024 * 64]; // 64KB 足够一次请求
std::pmr::monotonic_buffer_resource pool(buffer, sizeof(buffer));
RequestContext ctx(&pool);
// ... 处理请求 ...
// ctx 析构时,pool 复位,64KB 零碎分配一次性释放