标准STL容器默认不支持PMR内存池,必须显式传入std::pmr::polymorphic_allocator作为模板参数;如std::pmr::vector v{&pool},否则仍走默认new分配。

标准 STL 容器(如 std::vector、std::string)**默认不会自动从你的自定义 PMR 内存池分配内存**——它们压根不认 std::pmr::memory_resource*,只认符合 Allocator 概念的类型。想让它们用上你的池,必须显式传入一个包装了该资源的 std::pmr::polymorphic_allocator,并作为模板参数提供给容器。
为什么 std::vector 不能直接用 monotonic_buffer_resource?
因为 std::vector<int></int> 的完整类型是 std::vector<int std::allocator>></int>,它的第二个模板参数是 std::allocator,和 PMR 无关。你创建的 std::pmr::monotonic_buffer_resource 对象,它只是个裸指针目标,容器根本看不到、也不会去查全局默认资源(除非你改了全局设置,但那不推荐且不可控)。
- 错误写法:
std::pmr::monotonic_buffer_resource pool{buffer, size}; std::vector<int> v;</int>→ 完全没用,还是走new - 正确前提:必须用
std::pmr::polymorphic_allocator<t></t>把资源“绑”到具体类型T上 - 关键点:
polymorphic_allocator<int></int>和polymorphic_allocator<:string></:string>是不同实例,不能混用;但可以共享同一个memory_resource*
怎么把自定义 resource 塞进 std::vector?
不是直接传 resource 指针给 vector 构造函数,而是通过 std::pmr::polymorphic_allocator 中转,并作为容器的 Allocator 模板参数显式指定。
- 最简方式(推荐):
std::pmr::vector<int> v{&pool};</int>—— 这里std::pmr::vector是std::vector<int std::pmr::polymorphic_allocator>></int>的别名,构造时自动用&pool初始化其 allocator - 手动指定 allocator 类型(等价但啰嗦):
std::vector<int std::pmr::polymorphic_allocator>> v{std::pmr::polymorphic_allocator<int>{&pool}};</int></int> - 注意生命周期:
&pool必须比容器存活时间长;若pool是栈变量,容器不能逃逸出作用域 - 别写
polymorphic_allocator<void></void>:C++20 已废弃,且无法调用T的构造函数,会导致未定义行为
std::string 或 std::unordered_map 能这么用吗?
能,但得用对应的 std::pmr 别名,或者手动拼 Allocator 模板参数。别指望 std::string 自己识别 PMR 资源。
立即学习“C++免费学习笔记(深入)”;
-
std::pmr::string s{"hello", &pool};✅ ——std::pmr::string是std::basic_string<char std::char_traits>, std::pmr::polymorphic_allocator<char>></char></char>的别名 -
std::pmr::unordered_map<:string int> m{&pool};</:string>✅ —— 键值类型内部存储也会走该 allocator - 错误假设:
std::string s; s.get_allocator().resource() = &pool;❌ ——std::string没这个接口;get_allocator()返回的是std::allocator,不是 polymorphic 版本 - 若需混合使用(比如已有
std::vector接口),可封装一层:用using MyVector = std::vector<int std::pmr::polymorphic_allocator>>;</int>,再传MyVector{alloc}
常见崩溃原因:分配失败却没报错
这是 PMR 最容易被忽略的陷阱。自定义资源(如 monotonic_buffer_resource)在缓冲区满时,allocate() 直接返回 nullptr,而 std::pmr::vector 等容器内部**不做空指针检查**,后续 construct() 或写入就会解引用空指针,直接 crash。
- 调试阶段强烈建议包装 resource:重写
do_allocate,在返回前加assert(ptr != nullptr) - 生产环境别依赖 assert,应提前预估容量或换用支持回收的资源(如
unsynchronized_pool_resource) -
monotonic_buffer_resource不支持deallocate(),所有内存只能随 resource 对象销毁时一并释放——这意味着它只适合 request/frame 生命周期内的临时对象 - 多线程下慎用
synchronized_pool_resource:它的锁是全局一把,高并发小对象分配时性能可能比默认 new 还差 3–5 倍
真正要让“标准容器”用上你的池,核心就一条:别想着让它“自动感知”,老老实实把 polymorphic_allocator<t></t> 当作容器的第二个模板参数传进去。所有看似“自动”的别名(如 std::pmr::vector)背后,都是这一显式绑定在起作用。漏掉这一步,resource 就只是内存里的一个安静指针。


















