我第一次做内存优化。
不是为了更快。
是为了别抖。
线上延迟像心电图。
你去看。
发现一堆小对象在频繁 new/delete。
你想做池化。
然后你就开始碰 allocator。
当年:allocator 能用,但它太难“贯穿工程”
标准库容器早就支持 allocator。
你可以给 std::vector 一个自定义 allocator。
问题是。
allocator 是模板参数。
一旦你换了 allocator。
容器类型就变了。
std::vector<int> 变成了 std::vector<int, MyAlloc>。
类型一路传。
接口一路改。
你会很快放弃。
线上啪一下:我想做临时内存池,结果改动像雪崩
假设你写了个小服务。
每个请求都会构造一堆临时字符串、临时 vector。
你想用一个“请求级别的内存池”。
请求结束就整块释放。
这在工程上很香。
但如果你走传统 allocator 路线。
你得把 allocator 从最外层一路传到最里层。
你会发现。
这不是优化。
这是重写。
C++17:pmr 的核心想法——把分配策略从类型里拿出来
pmr 是 Polymorphic Memory Resource。
你可以先把它理解成。
“容器用一个指向资源的指针来分配内存”。
这样容器的类型不再因为 allocator 不同而改变。
标准库提供了一套对应的容器别名。
比如 std::pmr::vector、std::pmr::string。
#include <memory_resource>
#include <vector>
std::pmr::vector<int> v;
这行的重点是。
v 的类型不会因为你换资源而变。
你可以在运行期决定用哪个资源。
一个最常见的资源:monotonic_buffer_resource
它的味道很像。
“只往上长,不回收单个对象”。
#include <memory_resource>
#include <array>
std::array<std::byte, 4096> buf;
std::pmr::monotonic_buffer_resource pool(buf.data(), buf.size());
你把它当成一个小水池。
分配就从里面切一块。
不够了就再向上申请。
回收的时候。
你不是一个个 free。
你是直接把整个池 reset。
把容器挂到这个池上
#include <memory_resource>
#include <string>
std::pmr::string s{&pool};
std::pmr::vector<std::pmr::string> names{&pool};
names.push_back(s);
这里你会注意到。
容器构造时传了一个资源指针。
这就是 pmr 的关键入口。
你刚学会皱眉:那对象析构怎么办
pmr 不是跳过析构。
对象该析构还是析构。
它只是把“内存回收策略”换成了资源。
对于 monotonic 这种。
内存不会一个个归还。
你要在合适的时机 reset/销毁资源。
这很适合请求级别、批处理级别的临时对象。
不适合“活很久、随时删除”的那类数据结构。
关键结论
pmr 的价值是。
让你能在不改容器类型的前提下,切换内存分配策略。
小结:当你真的需要管内存时,pmr 比 allocator 传参更像工程
当年 allocator 的路子太“模板化”。
它能做。
但很难落到大工程。
C++17 的 pmr 把它变成运行期选择。
你可以把优化收敛在少数几个入口。
不必把类型改动扩散成雪崩。