必须显式传入同一memory_resource*指针,如std::pmr::vector{res.get_resource()};资源对象生命周期须长于所有容器,否则导致野指针或未定义行为。

std::pmr::vector 怎么共享同一个 memory_resource
关键不是“怎么创建”,而是“怎么确保所有容器都用同一个 std::pmr::memory_resource*”。默认构造的 std::pmr::vector 会绑定到全局默认资源(std::pmr::new_delete_resource()),完全不复用。必须显式传入同一资源指针。
实操建议:
- 用
std::pmr::monotonic_buffer_resource或std::pmr::synchronized_pool_resource创建一个长期存活的对象(比如放在类成员或静态变量里) - 所有容器构造时统一传它的
get_resource()结果,例如:std::pmr::vector<int>{res.get_resource()}</int> - 别用临时资源对象——比如在函数内建
monotonic_buffer_resource然后传给 vector,出作用域后资源析构,vector 再访问就是野指针
为什么 std::pmr::string 和 std::pmr::vector 不能直接混用同一池
能混用,但前提是它们底层分配器使用的 memory_resource 确实是同一个实例。常见错误是:以为用了 std::pmr::string 就自动进了池,其实它默认仍走全局资源;或者给 string 传了池 A,vector 传了池 B 的指针(哪怕两个池类型一样、参数一样),内存也互不共享。
典型陷阱:
立即学习“C++免费学习笔记(深入)”;
【极品模板】出品的一款功能强大、安全性高、调用简单、扩展灵活的响应式多语言企业网站管理系统。 产品主要功能如下: 01、支持多语言扩展(独立内容表,可一键复制中文版数据) 02、支持一键修改后台路径; 03、杜绝常见弱口令,内置多种参数过滤、有效防范常见XSS; 04、支持文件分片上传功能,实现大文件轻松上传; 05、支持一键获取微信公众号文章(保存文章的图片到本地服务器); 06、支持一键
-
std::pmr::string s1{"hello", &pool1}和std::pmr::string s2{"world", &pool2}—— 即使pool1和pool2是相同类型且同配置,只要不是同一对象,内存就不互通 - 字符串字面量构造(如
std::pmr::string{"hello"})不会触发 pmr 分配,走的是隐式转换到const char*,再调用非 pmr 构造函数 - 拷贝赋值(
s1 = s2)时,若s1和s2的get_allocator().resource()不同,内部会重新分配内存,导致跨池拷贝——性能差且破坏复用意图
std::pmr::polymorphic_allocator 的 resource 生命周期谁管
它不管。std::pmr::polymorphic_allocator 是个轻量包装,只存一个 memory_resource* 指针,不持有资源对象本身。所以资源对象的生命周期必须比所有使用它的容器更长。
这意味着:
- 资源对象不能是栈变量(除非容器也严格限定在同一作用域)
- 如果资源是类成员,该类实例必须比所有依赖它的容器活得久;否则容器析构时可能尝试用已销毁的 resource 释放内存,触发未定义行为
-
std::pmr::synchronized_pool_resource内部有锁和子池管理,适合多线程反复分配小对象;monotonic_buffer_resource无锁、不可回收、只能整体释放——选错类型会导致内存泄漏或竞争,不是“能跑就行”
容器 swap 后内存还属于原池吗
是的,swap 只交换容器控制块(指针、size、capacity),不挪动元素内存。只要两个容器用的是同一个 memory_resource,swap 后它们依然从那个池分配/释放。
但要注意边界情况:
- 如果 a 用池 A,b 用池 B,调
a.swap(b)后,a 仍归池 A 管,b 归池 B 管——swap 不改变 allocator 绑定关系 - 用
std::swap(a, b)(ADL 版本)效果同上;但若误用std::swap的泛型版本(非特化),会触发拷贝构造+析构,引发跨池分配,极慢且危险 - move 构造/赋值也保持原 allocator,这点和普通容器一致,但容易被忽略:move 并不“转移池”,只是转移容器状态
最易被忽略的一点:pmr 容器的 get_allocator() 返回的 polymorphic_allocator 是临时对象,不能靠它取地址来判断是否同源——得比对 alloc.resource() == other_alloc.resource() 才算真正共享。









