从STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象(所有的数值)都存放在容器之内,而容器一定需要配置空间以置放资料。
STL空间配置器的结构如图:
那么就分三个部分介绍:
一、构造和析构的基本工具:construct()和destroy()
1、construct()接受一个指针p和一个初值value,该函数的用途就是将初值设定到指针所指的空间上。
2、destroy()有两个版本,第一个版本接受一个指针,准备将该指针所指之物析构掉。这很简单,直接调用该对象的析构函数即可。
第二版本接受first和last两个迭代器,准备将[first,last)范围内的所有对象析构掉。
二、空间的配置与释放:std::alloc
1、C++的内存配置基本操作是::operator new(),内存释放基本操作是::operator delete()。
2、考虑到小型区块所可能造成的内存破碎问题,STL设计了双层级配置器。
3、第一级配置器:
(1)allocate()直接使用malloc(),deallocate()直接使用free()。
(2)模拟C++的set_new_handler()以处理内存不足的状况。
4、第二级配置器
(1)当配置区块超过128bytes时,便调用第一级配置器。
(2)当配置区块小于128bytes时,采用自由链表(free list)+内存池(memory pool)处理。16个自由链表负责16个小型区块的次配置能力。内存池以malloc()配置而得。如果内存不足,转调用第一级配置器(那有处理程序)。
三、内存基本处理工具
STL定义有5个全局函数:
现在来说明一下这下面3个函数的功能:
1、uninitialized_copy
template<class InputIterator,class ForwardIterator> ForwardIterator uninitialized_copy(InputIterator first,InputIterator last,ForwardIterator result);
迭代器first指向输入端的起始位置
迭代器last指向输入端的结束位置(前闭后开区间)
迭代器result指向输出端(欲初始化空间)的起始处
uninitialized_copy()使我们能将内存的配置与对象的构造行为分离开来。如果作为输出目的地[result,result+(last+first))范围内的每一个迭代器都指向未初始化区域,则 uninitialized_copy()会使用copy constructor,给身为输入来源之[first,last)范围内的每一个对象产生一份复制品,放进输出范围中。uninitialized_copy对实现一个容器有很大帮助,因为容器的全区间构造函数(range construct)通常由两个步骤完成:
(1)配置内存区块,足以包含范围内的所有元素。
(2)使用uninitialized_copy(),使改内存区块上构造函数。
2、uninitialized_fill
template<class ForwardIterator,class T> void uninitialized_fill(ForwardIterator first,ForwardIterator last,const T& x);
迭代器first指向输出端(欲初始化空间)的起始处
迭代器last指向输出端(欲初始化空间)的结束处(前闭后开区间)
x表示初值
uninitialized_fill()也能使我们能将内存的配置与对象的构造行为分离开来。如果[first,last)范围内的每个迭代器都指向未初始化的内存,那么uninitialized_fill()会在该范围内产生x的复制品。
3、uninitialized_fill_n
template<class ForwardIterator,class Size,class T> ForwardIterator uninitialized_fill(ForwardIterator first,Size n,const T& x);
迭代器first指向欲初始化空间的起始处
n表示欲初始化空间的大小
x表示初值
uninitialized_fill_n()也能使我们能将内存的配置与对象的构造行为分离开来。它会为指定范围内的所有元素设定相同的初值。
如果[first,first+n)范围内的每个迭代器都指向未初始化的内存,那么如果[first,last)范围内的每个迭代器都指向未初始化的内存,那么uninitialized_fill_n()会调用copy construct,在该范围内产生x的复制品。