欢迎光临散文网 会员登陆 & 注册

3 简单的空间配置器

2023-03-06 15:05 作者:HC_0702  | 我要投稿

本项目GitHub: HuangCheng72/HCSTL: 我的STL实现 (github.com): https://github.com/HuangCheng72/HCSTL

进入正文。

我们在上一篇中留下了一个问题还没有解决,就是T为non-POD类型的时候,不能delete回收内存空间的问题。这里不对问题的来龙去脉作过多回顾,需要回顾请看上一篇。

我们在上一篇中提到,我们new一个类的对象,涉及了两个操作:

  1. 申请一块内存空间,用来存放这个对象。

  2. 在这块空间上根据参数输入调用类相应的构造函数,创建这个对象(初始化内存空间的各个参数)。

而T为POD类型的时候,只需要进行1的操作,申请内存空间,就可以存放数据了。

在上一篇中,我们构造对象使用的是定位new(placement new),在网上查资料发现定位new运算符的一个特点是,它能在堆和栈上创建对象,而我们知道普通的new和delete是从堆上创建对象和回收内存到堆上的,因此定位new使用之后是不可以使用普通的delete去回收空间(谁知道你是不是在栈上创建的),只能显式调用对象析构函数来空出内存空间。这也解决了我们之前的一大疑惑。而普通的new申请出来的内存空间只能由普通的delete回收。

所以我们可以换个思路,分离这两个操作,我们只从堆上申请内存,也只回收到堆上,然后在申请到的内存上创建对象,对象析构之后再回收到堆上。这样不就能解决我们的non-POD类型的内存无法回收造成浪费的问题了。

C++提供了两个全局函数 ::operator new() 和 ::operator delete() ,这两个函数是对C语言 malloc 和 free 的封装,起到的效果是一样的。

所以我们修改vector中的辅助函数和两个带参构造器以及析构器:

run一下,顺利运行。

因为STL不可能只有一个vector容器需要内存管理,而且这么实现代码可读性也比较差。为了提高代码的复用性和可读性,我们可以考虑分离出一个专门的组件,负责内存的管理(目前只有申请和释放)和对象的构造和析构。这就是STL六大组件中的空间配置器(allocator)。

目前,我们先实现一个最简单的空间配置器,空间配置部分简单封装 ::operator new 和 ::operator delete 即可,对象构造则是简单封装定位new,析构则是简单调用类的析构器即可。

请建立两个头文件,allocator.h 和 constructor.h,分别实现两个部分。

allocator.h:

constructor.h:

以该空间配置器为基础,同时为了提高代码的可读性,vector的实现如下:

main.cpp的简单测试:

顺利运行。

欢迎访问本项目的GitHub仓库,如果对您有帮助,麻烦给项目一个star,谢谢!

HuangCheng72/HCSTL: 我的STL实现 (github.com): https://github.com/HuangCheng72/HCSTL

3 简单的空间配置器的评论 (共 条)

分享到微博请遵守国家法律