关于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类似的方法……所以就不写了。(嗬嗬嗬

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

完整源码下载

时间: 2024-10-17 21:17:49

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

sass基础用法

sass基础用法 SASS是什么 传统的CSS是一种单纯的描述性样式文件,然而SASS可以对CSS进行预编译处理. 在SASS源码中可以使用变量.函数.继承等动态语言的特性,并且可以编译成CSS文件. 安装与使用 安装 由于sass是ruby写的,所以想要使用sass就需要安装ruby环境.然后再使用gem安装sass. 输入下面的命令进行安装sass: gem install sass 可以使用sass -v命令查看sass的版本. 使用 新建一个后缀名为.scss源码文件,就可以编辑sass

游标基础用法

Create PROCEDURE P_InsertSubject@SubjectId intASDECLARE rs CURSOR LOCAL SCROLL FORselect studentid from student where StudentGradu = 1OPEN rsFETCH NEXT FROM rs INTO @tempStudentIDWHILE @@FETCH_STATUS = 0BEGINInsert SelSubject values (@SubjectId,@temp

Cocos数据篇[3.4](6) ——SQLite3数据库基础用法

[唠叨] 在Cocos2d-x中,简单数据存储,可以使用UserDefault.那么如何存储大量,不规则的数据?我们可以使用 SQLite数据库 存储数据.SQLite 是使用非常广泛的 嵌入式数据库 ,它有小巧 .高效.跨平台.开源免费和易操作的特点.所以大量的被用于手机.PDA.MP3播放器.以及机顶盒设备. SQLite数据库是使用C语言来编写的,因此在Cocos2d-x使用SQLite也是得心应手. 本文介绍一下SQLite3数据库的基础用法:增删改查. PS:另外对于SQLite的可视

sed命令基础用法

    sed(Stream EDitor)简介 sed是一个流编辑器编辑器,本身是一个管道命令,主要以行为单位处理文本文件,可以将数据进行替换.删除.新增.选取等特定工作:sed并不会处理文本文件本身,而是每当处理一个文件时,按顺序逐行读取到模式空间(内存)中,而后在模式空间中完成编辑,把编辑的结果输出到屏幕上,接着处理下一行,反复操作,直到文件结尾. 模式空间:将读取的内容放在内存中的一块区域编辑,这些内存空间就称为模式空间 格式: sed [options]    'Address Com

2017.04 vue学习笔记---08表单控件绑定---基础用法

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> div{ margin-bottom: 30px; } </style> <script src="js/vue.js"></script> <

UIButton的最基础用法

UIButton的最基础用法 UIButton (1) 创建显示一个Button      //演示UI中按钮类UIButton使用 //需求: 想要在界面上显示一个按钮 //解决:   使用UIButton按钮类  //<1>创建按钮,一般需要指定按钮的风格 //系统样式的按钮:  UIButtonTypeSystem //如果创建带图片的: 一般选用UIButtonTypeCustom //圆角矩形: ios7不再使用UIButtonTypeRoundedRect //UIButtonTy

Vue组件基础用法

前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需,使用不同的组件来拼接页面.这种开发模式使前端页面易于扩展,且灵活性高,而且组件之间也实现了解耦.本文将详细介绍Vue组件基础用法 概述 组件是一个自定义元素或称为一个模块,包括所需的模板.逻辑和样式.在HTML模板中,组件以一个自定义标签的形式存在,起到占位符的功能.通过Vue.js的声明式渲染后,

sed基础用法

在linux系统中,sed的文本处理无疑是一个非常强大的工具,用好sed可以使我们工作效率成倍提升,下面就小结一下sed的常用命令参数,只需关注常用的即可. 选项参数 首先来一发sed --help了解一下常用的参数 # sed --help Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... -n  忽略打印输出,一般是避免默认输出,只有我们处理的那一行文本会显示在屏幕上 -e  在命令行进行文本的处理

初识salt之saltstack配置应用以及基础用法

一.测试是否能管理client 使用模块cmd.run 可以查看到client的ip地址 [[email protected]_server ~]# salt '*' cmd.run 'ip a' salt_client1:     1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN          link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00