0

0

C++怎么自定义内存分配器(allocator)_C++内存管理与自定义分配器实现

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-11-17 10:23:02

|

919人浏览过

|

来源于php中文网

原创

自定义内存分配器通过实现allocate/deallocate机制优化内存管理,适用于高频小对象分配场景。需定义value_type、pointer等类型及allocate(n)和deallocate(p, n)函数,支持rebind以适配不同类型。C++17起construct/destroy非必需,由std::allocator_traits统一处理。示例包括基于malloc的简单分配器和内存池分配器:后者预分配大块内存,维护空闲链表提升分配效率,适用于固定大小对象。使用时注意状态传递、线程安全与内存互操作性,避免全局重载new/delete,优先用于特定容器如std::vector以提升性能。

c++怎么自定义内存分配器(allocator)_c++内存管理与自定义分配器实现

自定义内存分配器在C++中是一种提升性能或控制内存行为的常用手段,尤其是在处理大量小对象、需要内存池、或者对内存布局有特殊要求的场景下。标准库中的容器(如std::vectorstd::list等)都支持通过模板参数传入自定义allocator。要实现一个自定义分配器,你需要遵循Allocator概念的要求。

理解标准Allocator接口

C++标准中的Allocator是一个类模板,需提供一些特定的类型定义和成员函数。最基本的接口包括:

  • value_type:被分配类型的别名
  • pointer:指向value_type的指针类型
  • const_pointer:常量指针类型
  • reference:引用类型
  • const_reference:常量引用类型
  • size_type:无符号整数类型,表示大小
  • difference_type:有符号整数类型,表示指针差值
  • allocate(n):分配n个value_type大小的内存块,不构造对象
  • deallocate(p, n):释放从p开始的n个对象所占内存,不析构
  • construct(ptr, args...):在指定地址构造对象(C++17前)
  • destroy(ptr):显式调用析构函数(C++17前)

从C++17开始,constructdestroy不再是必须的,因为标准库改用std::allocator_traits来统一管理构造与析构。

实现一个简单的自定义分配器

下面是一个基于mallocfree的简单分配器示例,可用于替代std::allocator

立即学习C++免费学习笔记(深入)”;

#include 
#include 

template struct MyAllocator { using value_type = T; using pointer = T; using const_pointer = const T; using reference = T&; using const_reference = const T&; using size_type = std::size_t; using difference_type = std::ptrdiff_t;

// 支持不同类型的再绑定
templatezuojiankuohaophpcntypename Uyoujiankuohaophpcn
struct rebind {
    using other = MyAllocatorzuojiankuohaophpcnUyoujiankuohaophpcn;
};

MyAllocator() = default;

templatezuojiankuohaophpcntypename Uyoujiankuohaophpcn
MyAllocator(const MyAllocatorzuojiankuohaophpcnUyoujiankuohaophpcn&) {}

// 分配原始内存
pointer allocate(size_type n) {
    if (n == 0) return nullptr;
    void* ptr = std::malloc(n * sizeof(T));
    if (!ptr) throw std::bad_alloc();
    return static_castzuojiankuohaophpcnpointeryoujiankuohaophpcn(ptr);
}

// 释放内存
void deallocate(pointer p, size_type) {
    if (p) std::free(p);
}

};

这个分配器可以用于std::vector

std::vector> vec;
vec.push_back(1);
vec.push_back(2);

高级自定义:内存池分配器

若想进一步优化性能,可实现一个内存池分配器,避免频繁调用系统malloc/free。基本思路是预先分配一大块内存,然后从中切分小块返回。

Magic Eraser
Magic Eraser

AI移除图片中不想要的物体

下载

关键点:

  • 维护一个空闲链表(free list)
  • 只在内存池耗尽时向系统申请新页
  • 适用于固定大小对象的快速分配

简化版内存池分配器框架:

template
class PoolAllocator {
private:
    struct Block {
        Block* next;
    };
    Block* free_list = nullptr;
    char* current_block = nullptr;
    size_t remaining = 0;
void refill_pool() {
    current_block = new char[BlockSize];
    size_t num_objects = BlockSize / sizeof(T);
    free_list = reinterpret_castzuojiankuohaophpcnBlock*youjiankuohaophpcn(current_block);

    for (size_t i = 0; i zuojiankuohaophpcn num_objects - 1; ++i) {
        reinterpret_castzuojiankuohaophpcnBlock*youjiankuohaophpcn(current_block + i * sizeof(T))-youjiankuohaophpcnnext =
            reinterpret_castzuojiankuohaophpcnBlock*youjiankuohaophpcn(current_block + (i+1) * sizeof(T));
    }
    reinterpret_castzuojiankuohaophpcnBlock*youjiankuohaophpcn(current_block + (num_objects-1)*sizeof(T))-youjiankuohaophpcnnext = nullptr;
    remaining = num_objects;
}

public: using value_type = T; using pointer = T; using const_pointer = const T; using size_type = std::size_t;

templatezuojiankuohaophpcntypename Uyoujiankuohaophpcn
struct rebind {
    using other = PoolAllocatorzuojiankuohaophpcnU, BlockSizeyoujiankuohaophpcn;
};

PoolAllocator() = default;

templatezuojiankuohaophpcntypename Uyoujiankuohaophpcn
PoolAllocator(const PoolAllocatorzuojiankuohaophpcnU, BlockSizeyoujiankuohaophpcn&) {}

pointer allocate(size_type n) {
    if (n != 1) throw std::bad_alloc(); // 只支持单个对象
    if (remaining == 0) refill_pool();

    Block* slot = free_list;
    free_list = free_list-youjiankuohaophpcnnext;
    --remaining;
    return reinterpret_castzuojiankuohaophpcnpointeryoujiankuohaophpcn(slot);
}

void deallocate(pointer p, size_type) {
    if (p) {
        Block* slot = reinterpret_castzuojiankuohaophpcnBlock*youjiankuohaophpcn(p);
        slot-youjiankuohaophpcnnext = free_list;
        free_list = slot;
        ++remaining;
    }
}

};

使用方式:

std::vector> fast_vec;

注意事项与最佳实践

自定义分配器虽然强大,但也有几点需要注意:

  • 状态管理:如果分配器包含状态(如内存池指针),确保rebind能正确传递状态
  • 线程安全:默认情况下,分配器不保证线程安全,多线程使用时需加锁
  • 兼容性:两个分配器实例应能互相释放对方分配的内存(即“可互操作”)
  • 不要重载全局new/delete:除非必要,否则优先使用容器级分配器,避免影响整个程序

基本上就这些。自定义分配器的核心在于掌握allocate/deallocate机制,并根据需求优化内存获取策略。不复杂但容易忽略细节。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1434

2023.10.24

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

519

2023.09.20

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

312

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

521

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

48

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

188

2025.08.29

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

989

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

49

2025.10.17

桌面文件位置介绍
桌面文件位置介绍

本专题整合了桌面文件相关教程,阅读专题下面的文章了解更多内容。

0

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号