跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++17 PMR 内存管理详解:memory_resource 与 polymorphic_allocator

综述由AI生成C++17 引入的 std::pmr 模块提供了灵活的内存管理方案。通过 std::pmr::memory_resource 抽象基类定义标准分配接口,结合 std::polymorphic_allocator 多态分配器,用户可自定义内存策略如线程本地存储或内存池。文章解析了核心成员函数、使用示例及自定义实现方法,旨在提升代码性能与维护性,适用于多线程竞争优化及减少内存碎片场景。

RefactorPro发布于 2026/3/15更新于 2026/5/3025 浏览

在现代 C++ 编程中,高效且灵活的内存管理一直是追求的重要目标之一。 在 C++17 标准中,引入了 std::pmr::memory_resource 和 std::polymorphic_allocator 这两个强大的组件,它们为分配内存提供了高度的灵活性和可扩展性,使你可根据不同应用场景和需求,更加精细地控制内存的分配和释放过程。 以下是对这两个组件的详细解析。

一、std::pmr::memory_resource

(一) 基本概念

std::pmr::memory_resource 是一个定义了一套标准的分配内存接口的抽象基类。 该接口为用户统一处理不同分配内存策略,允许用户根据具体需求自定义分配内存,如线程本地分配内存、内存池分配等。

使用该抽象基类,可统一管理和使用不同分配内存器,提高了代码的可维护性和可扩展性。

(二) 主要成员函数

1. allocate(std::size_t bytes)

功能:该函数用来分配指定字节数的内存。在实际应用中,它会根据具体的分配内存策略来找合适的内存块,并把它分配给调用者。

参数:bytes 参数表示要分配的字节数。该参数是调用者根据自身需求传入的,它决定了要分配的内存大小。 返回值:函数返回分配的内存的指针。调用者可用该指针来访问和操作分配的内存。

2. deallocate(void* ptr, std::size_t bytes)

功能:此函数用来释放指定指针指向的内存。当调用者不再使用之前分配的内存时,就可调用该函数来释放该内存,这样其他程序可使用它。

参数:ptr 是要释放的内存的指针,指向之前分配函数分配的内存块的开始位置。bytes 是该内存块的大小,用来帮助分配内存器正确地释放内存。

注意:在调用释放函数时,需要确保传入的指针和大小与之前分配函数返回的指针和分配的大小一致,否则可能会泄漏内存或有其他未定义行为。

3. is_equal(const memory_resource& other) const noexcept

功能:该函数用来判断当前内存资源是否与另一个内存资源相等。这里的相等一般表示两个内存资源可互相替代使用,即它们的分配和释放内存行为是兼容的。

参数:other 是与当前内存资源比较的另一个内存资源对象。 返回值:如果两个内存资源相等,则返回真,否则返回假。该函数有时非常有用,如在需要判断两个不同容器是否使用相同内存资源时。

(三) 使用场景

1. 分配内存的灵活性

在不同应用场景中,可能需要不同分配内存策略。如,在多线程环境中,为了避免线程间的竞争和提高性能,可用线程本地分配内存策略。 std::pmr::memory_resource 允许用户根据这些不同需求自定义分配内存策略,从而提高程序的效率和效率。

2. 管理资源的统一性

在大型项目中,可用多种不同分配器,会导致不同分配器间的冲突和管理困难。std::pmr::memory_resource 提供的统一接口,可统一管理这些不同分配器,避免冲突,提高代码的可维护性。

二、std::polymorphic_allocator

(一) 基本概念

std::polymorphic_allocator 是一个多态分配器,它允许用户指定不同 std::pmr::memory_resource 对象来分配内存。

它是一个 T 模板参数表示分配器分配的元素类型的模板类。即 std::polymorphic_allocator 可按需分配不同类型的元素,且可用不同内存资源来分配。

(二) 主要成员函数

1. allocate(std::size_t n)

功能:该函数用来分配 n 个元素的内存。它会调用关联的 std::pmr::memory_resource 对象的分配函数来实际分配内存。 参数:n 表示要分配的元素数量。该参数决定了会根据 T 元素类型的大小计算的要分配的内存大小。 返回值:返回指向分配的第一个元素的位置的分配的内存的指针。

2. deallocate(T* ptr, std::size_t n)

功能:此函数用来释放指定指针指向的内存。它会调用关联的 std::pmr::memory_resource 对象的释放函数来实际释放内存。

参数:ptr 是指向之前分配函数分配的内存块的开始位置的要释放的内存的指针。n 是该内存块中用来帮助内存资源正确地释放内存的元素数。

3. resource()

功能:该函数来取当前分配器使用的 std::pmr::memory_resource 对象。用它用户可了解当前分配器所使用的内存资源,且可在需要时切换或管理。 返回值:返回当前分配器使用的内存资源对象的指针。

(三) 使用示例

#include <memory_resource>
#include <iostream>
#include <vector>

int main() {
    // 创建默认内存资源
    std::pmr::memory_resource* default_resource = std::pmr::get_default_resource();
    // 创建使用默认资源的多态分配器
    std::pmr::polymorphic_allocator<int> alloc(default_resource);
    // 使用多态分配器分配内存
    std::pmr::vector<int, std::pmr::polymorphic_allocator<int>> vec(alloc);
    // 添加元素
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);
    // 输出元素
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}

这里,首先用 std::pmr::get_default_resource() 函数取了一个默认内存资源。然后创建了一个使用该默认资源的分配多态分配器。 接着使用该分配器创建了一个 std::pmr::vector 容器 vec,并向其中添加了一些元素。最后,遍历容器并输出其中的元素。

(四) 自定义内存资源

用户还可自定义 std::pmr::memory_resource 的继承类,以实现特定的分配内存策略。如,可实现一个线程本地的内存池分配器,或一个基于映射文件的分配内存器。

自定义内存资源示例
#include <memory_resource>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>

class ThreadLocalMemoryResource : public std::pmr::memory_resource {
private:
    std::mutex mutex_;
    std::vector<char> buffer_;
public:
    void* do_allocate(std::size_t bytes, std::size_t align) override {
        std::lock_guard<std::mutex> lock(mutex_);
        buffer_.resize(buffer_.size() + bytes);
        return buffer_.data() + buffer_.size() - bytes;
    }

    void do_deallocate(void* ptr, std::size_t bytes, std::size_t align) override {
        // 不需要释放线程本地内存资源
    }

    bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
        return this == &other;
    }
};

int main() {
    // 创建自定义内存资源
    ThreadLocalMemoryResource custom_resource;
    // 创建一个使用自定义资源的多态分配器
    std::pmr::polymorphic_allocator<int> alloc(&custom_resource);
    // 使用多态分配器分配内存
    std::pmr::vector<int, std::pmr::polymorphic_allocator<int>> vec(alloc);
    // 添加元素
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);
    // 输出元素
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}

这里,定义了从 std::pmr::memory_resource 继承的叫 ThreadLocalMemoryResource 的自定义内存资源类。

在 do_allocate 函数中,按内存缓冲使用一个 std::vector,每次分配内存时,将缓冲的大小增加到要求的字节数,并返回新分配内存的指针。

在 do_deallocate 函数中,因为是线程本地内存资源,不需要释放内存,因此无需操作。在 do_is_equal 函数中,比较对象的地址来判断两个内存资源是否相等。

在主函数中,创建了一个 ThreadLocalMemoryResource 对象 custom_resource,并使用它创建了一个分配多态分配器。 然后使用该分配器创建了一个 std::pmr::vector 容器 vec,并向其中添加了一些元素。最后,遍历容器并输出其中的元素。

三、总结

std::pmr::memory_resource 和 std::polymorphic_allocator 是 C++17 中引入的重要的管理内存工具,它们为分配内存提供了更高的灵活性和统一性。

自定义内存资源,用户可按需实现高效的管理内存策略,如在多线程环境中使用线程本地分配内存来提高性能,或使用内存池分配来减少内存碎片。

这些工具的引入使得 C++ 在管理内存方面更加强大和灵活,可更好地满足不同应用场景的需求。同时,它们也提高了代码的可维护性和可扩展性,使得你可更加轻松地管理和优化内存使用。

在实际应用中,可选择合适的内存资源和分配器,并结合自定义内存资源,实现更加高效和灵活的管理内存。

如,在对性能要求极高的场景中,可用自定义的内存池分配器来减少分配和释放内存的成本;在多线程环境中,可用线程本地内存资源来避免线程间的竞争。 总之,std::pmr::memory_resource 和 std::polymorphic_allocator 为 C++ 你提供了强大的管理内存能力,值得深入应用和探索。

目录

  1. 一、std::pmr::memory_resource
  2. (一) 基本概念
  3. (二) 主要成员函数
  4. 1. allocate(std::size_t bytes)
  5. 2. deallocate(void* ptr, std::size_t bytes)
  6. 3. isequal(const memoryresource& other) const noexcept
  7. (三) 使用场景
  8. 1. 分配内存的灵活性
  9. 2. 管理资源的统一性
  10. 二、std::polymorphic_allocator
  11. (一) 基本概念
  12. (二) 主要成员函数
  13. 1. allocate(std::size_t n)
  14. 2. deallocate(T* ptr, std::size_t n)
  15. 3. resource()
  16. (三) 使用示例
  17. (四) 自定义内存资源
  18. 自定义内存资源示例
  19. 三、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Python 实现月相计算与可视化系统
  • C++ 核心就业方向与职业发展
  • Windows 11 配置 CUDA 版 llama.cpp 实现 GGUF 模型本地离线聊天
  • Effective Modern C++ 条款 35:基于任务与基于线程编程的对比与实践
  • Django REST Framework 企业级 API 架构与性能优化
  • JavaScript 基础语法与核心概念详解
  • 鸿蒙操作系统开发指南:从入门到应用模型实战
  • AI Agent 生产级框架实战:架构、记忆与工具调用
  • Webnovel Writer:基于 Claude Code 的长篇网文 AI 创作系统
  • AI 量化交易系统构建指南:从数据清洗到实盘执行
  • 鸿蒙 6 正式发布:功能升级构建跨设备安全流畅新生态
  • 机械控制工程与自动控制原理期末复习:核心考点与真题解析
  • 多模态模型开发实战:文本、图像与语音融合指南
  • MES 生产制造执行系统:SpringBoot 后端与 Vue 前端实现
  • Python 字节码逆向工具 pycdc:从黑盒到透明
  • VLM Unlearning 技术路线论文梳理
  • ARIS 开源:基于 Claude Code 的自动化科研与论文工作流
  • Python 包管理新范式:极速工具 uv 深度解析
  • Midjourney 使用指南
  • 前端程序员转大模型:全面转型攻略与学习路径

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online