首页 > 代码库 > 关于allocator的一些基础用法以及简易的vector实现

关于allocator的一些基础用法以及简易的vector实现

首先,关于allocator戳旁边→维基百科-分配器(C++)

这次我只用了其中的一部分API,来实现一个简易的vector容器,这个简易版vector实现了插入、删除、查找等简易功能,由于对右值的理解不足,所以这次并未实现关于右值的API。

【MSDN-class allocator_base API】

此次用到的有:

  • allocate - 用于分配、再分配空间
  • construct - 用于构造对象
  • destroy - 用于销毁对象(调用其构造函数)

 接下来开始,用例子一点点的说明如何使用allocator来编写一个vector类。

完整的源码在最下面可以下载。


首先,先给出一些typedef

typedef T           value_type;typedef T*          pointer;typedef const T*    const_pointer;typedef T*          iterator;typedef const T*    const_iterator;typedef T&          reference;typedef const T&    const_reference;typedef size_t      size_type;typedef ptrdiff_t   different_type;

其中T为typename,此处还用了指向T的指针来实现迭代器的用途。在使用typedef后,可更方便的理解代码,增强可读性。


 关于这个Vector类中的allocator,我选择了包含而非私有继承的方式,个人感觉这样的代码可读性更高,更易于修改维护。

类的私有部分,有如下四个成员:

//存储区std::allocator<value_type> _alloc_vec;//指向首位的指针pointer _first;//指向末位的指针pointer _last;//记录当前容量size_type _capacity;

allocator用来分配内存,存储元素;两个T*类型的指针分别指向Vector的开始以及结尾;size_type类型的_capacity则用来记录Vector的当前容量,在容量不足时就扩充。


 然后是成员函数,成员函数我是根据MSDN上提供的来编写的,所以全是公有成员函数,但是也足够完成这个简易的类了。

首先,构造函数、复制构造函数、析构函数以及重载的‘=‘符号

//默认构造函数Vector(size_type _size = 256) :  _first(_alloc_vec.allocate(_size)),  _last(_first),
  _capacity(_size){}
//复制构造函数Vector(const Vector& Right) :  _first(_alloc_vec.allocate(Right._capacity)),  _last(_first),
  _capacity(Right._capacity)
{
  for (auto p : Right)    _alloc_vec.construct(_last++, p);}//默认析构函数~Vector() = default; //重载‘=‘Vector& operator=(const Vector<T>& Right){  return Vector(Right);}

默认构造函数用了一个默认大小为256的_size参数来初始化对象,预分配一个不算太小的内存空间,也方便将来扩充。

_first(_alloc_vec.allocate(_size))

这一句的作用,等同于

_first = _alloc_vec.allocate(_size);

即给_alloc_vec分配一个大小为_size的空间,并且将_first指向其首位。具体函数声明请戳MSDN。

之后,由于没有给对象中添加元素,所以_last与_first指向相同的地址,即_alloc_vec的首位,然后将_size的值存入_capacity。

关于拷贝构造函数,先是用capacity()函数来获取Right的容量,然后让调用对象分配一个相同大小的空间,并且将两个指针都指向其首位,然后记录容器大小,接着进入函数体,用for循环将Right中的元素都拷贝至调用对象中,并且修改_last指向的位置。

注意,无论是何种构造函数,_last指向的位置都是最后一个元素的下一位。

至于析构函数则直接使用默认析构函数,而等号就直接调用复制构造函数。(才不是因为偷懒


 然后是pop_back()以及push_back()这两个较容易实现的成员函数。

//删除末尾元素void pop_back(){    _alloc_vec.destroy(--_last);}//将元素插入末位void push_back(reference val){    if (size() >= _capacity)    {        _alloc_vec.allocate(_capacity);        _capacity *= 2;    }    _alloc_vec.construct(_last++, val);}

pop_back()中调用了destroy函数,这个函数将会调用自减1之后的_last指针所指向的对象的析构函数,销毁该对象,而这一动作完成后,_last仍旧指向最后一位元素的下一位。

push_back()在将元素加入Vector之前,会检查容量是否足够分配空间,若是不够,则调用allocate来分配更多的空间;将元素加入,调用了construct,这个函数将调用类型为T的构造函数,并且在将其加入之后,将_last后移一位。


 然后好像那三个函数就介绍完了……剩下的Vector中的insert和erase函数也就是运用了与push_back以及pop_back类似的方法……所以就不写了。(嗬嗬嗬

至于其他的都是一些对指针的操作……嗯就这样吧……(逃

【完整源码下载】

关于allocator的一些基础用法以及简易的vector实现