应确保memory_resource生命周期长于polymorphic_allocator,如用静态/全局对象或类成员;避免临时resource导致悬空指针。

std::pmr::polymorphic_allocator 怎么初始化才不崩溃
直接传裸指针给 std::pmr::polymorphic_allocator 构造函数是常见崩溃源头——它不接管内存生命周期,只借用 std::pmr::memory_resource*。你得确保该指针在整个 allocator 生命周期内有效。
典型错误:临时 std::pmr::monotonic_buffer_resource 对象被析构,但后续还用它创建的 allocator 分配容器:
auto make_bad_alloc() {
std::pmr::monotonic_buffer_resource res;
return std::pmr::polymorphic_allocator<int>{&res}; // ❌ res 离开作用域就悬空
}
- 正确做法:把 resource 提升为静态、全局或长生命周期对象(比如类成员)
- 更安全:用
std::pmr::get_default_resource()作兜底,它永不析构 - 调试技巧:重载
do_allocate打日志,或用 AddressSanitizer 检查 use-after-free
std::pmr::vector 和普通 vector 的行为差异在哪
std::pmr::vector 是模板别名,本质是 std::vector<t std::pmr::polymorphic_allocator>></t>,但它的构造和赋值逻辑容易让人误判。
关键区别在「资源传播」:默认拷贝/移动构造时,allocator 不会自动复制,而是用目标容器当前绑定的 resource —— 这和 std::allocator 完全不同。
立即学习“C++免费学习笔记(深入)”;
- 显式传递 allocator:用
std::pmr::vector<int>{std::pmr::polymorphic_allocator<int>{&res}}</int></int> - 从普通 vector 转换?不行,没有隐式转换;必须用范围构造 + 显式 allocator:
std::pmr::vector<int>{v.begin(), v.end(), alloc}</int> - emplace_back 可能触发 reallocation:新内存仍来自原 allocator 绑定的 resource,不是当前栈上临时 res
monotonic_buffer_resource 和 synchronized_pool_resource 怎么选
选错 resource 类型会导致内存泄漏或性能断崖——它们根本不是“换汤不换药”的替代品。
std::pmr::monotonic_buffer_resource 是单向分配器,不支持 deallocate;std::pmr::synchronized_pool_resource 支持释放,但有线程同步开销和固定块大小限制。
- 适合 monotonic:短生命周期批量操作(如解析一帧数据),且确定不会中途释放单个对象
- 适合 synchronized_pool:高频小对象分配(
- 注意:pool resource 的最大块大小由构造时
std::pmr::pool_options控制,默认可能太小,导致 fallback 到 upstream resource(比如 malloc) - 实测提示:用
res.allocated_bytes()和res.current_bytes()监控实际使用,别只看 peak
自定义 memory_resource 时 operator new/delete 为什么没被调用
这是最隐蔽的坑:继承 std::pmr::memory_resource 并重写 do_allocate/do_deallocate 后,发现你的日志没打印、断点没进——大概率是因为你忘了 final 关键字或虚析构函数。
std::pmr::memory_resource 的接口全是 protected virtual,且要求派生类提供 public 虚析构函数,否则多态调用会失败(编译可能过,运行时调用基类空实现)。
- 必须加
virtual ~my_resource() override = default; - 不要重载全局
operator new:pmr 机制完全绕过它,只走 resource 的虚函数 - 调试建议:在
do_allocate开头强制assert(!"called"),确认是否真被调用 - 兼容性注意:C++17 标准只要求
do_allocate/do_deallocate/do_is_equal,别多写未定义接口
resource 的生命周期管理、allocator 的传播规则、以及不同 resource 的语义边界——这三处稍不留神就会让 pmr 从优化变成负优化。别依赖文档里的“看起来很美”,先用 current_bytes() 和 ASan 实锤内存路径。










