vector的意思就是向量,就是一个顺序表的意思,这个顺序表可以存任意的类型,因为其线性的内存特点,所以在stl里是经常被使用的存在。
vector
vector既然要能储存任意的变量,那么就必须使用模板:
这里的T就是变量类型,Alloc是内存池,这里先不多介绍不是vector的重点,后面我单独提出来讲。
vector的成员变量
因为vector本质就是顺序表,所以它的成员变应该是一个指针,一个size,一个capacity,但是通过查阅stl的官方开源代码,发现是一下的一种成员形式:
这里我们看到源码里面将Ttypedef成了value_type 所以看到它就是类型变量名的意思,iterator就是对应的指针。
用start变量,即T*的指针来指向空间的开始,然后用finish变量来指向内容的结尾的下一个地址,用end_of_storage来指向存储空间的结尾的下一个地址:
vector的成员函数和相关的全局函数
构造、析构,赋值
首先讲的函数就是和构造相关的操作
构造函数
这里构造函数主要是默认构造,拷贝构造,带参构造,迭代器构造,初始值设定项列表构造,右值引用构造。这里的右值引用我先不讲,因为我还没学。后面补上,迭代器还有读者不清楚的可以看这一篇文章:c++迭代器介绍。
其中初始值设定项列表和右值引用是在c++11之后才有的。
默认构造
默认构造就是构造一个什么内容都没有的容器。
带参构造
带参构造支持:
写成函数就是这个样子。如果只写一个参数,那么就以T的默认构造的值来进行构造。这里要补充一下,为了让所有变量都支持T()这种写法,所以将所有的编译器自带的变量也支持的带参、默认了:
所以我们以int的vector为例:
拷贝构造
拷贝构造就是我们传一个预先构造好的同类型vector,让后创建和它相同值的vector出来:
其中的b和c都是拷贝构造。
迭代器构造
迭代器构造就是可以用一个容器的迭代器开始和结束来实现构造,那么它的优点就很明显,可以跨容器构造:
初始值设定项列表构造
这个可能对大家有点陌生,可以看看我的这一篇博客,详细介绍了它c++ 初始值设定项列表(initializer_list)-CSDN博客
那么这里就不多介绍,看一个例子就行了:
其他函数
迭代器类
不会迭代器的可以看这一篇:c++迭代器的介绍-CSDN博客
里面详细介绍了迭代器,这里就不多讲了,我在之前的string类里面也详细讲了迭代器,所有容器迭代器基本上都是这几个函数。具体不同都是因为内存的结构不一样导致的。只会少不会多。
容器内存操作类
有几个比较常见的我就不说了。提一下容易错的
max_size和capacity
max_size和capacity是不一样的,max_size是我们一直往后存n个数,能存的极限是多少,一般就是size_t类的-1。
capacity是一直往后存,不扩容的情况下能存的极限是多少,也就是当前new的内存的长度。
resize
就是你要增长就按对应的值增长
如果是长度比之前小,就是缩短,如果是增长,且你不穿第二个参数,就是用默认值增长,这里的默认值是T(),你传了就是用你的。
reserve
我们先看扩大:
发现它是属于绝对听从命令的
然后看缩小
我们发现,它绝对不缩容。
那么和string不一样的点就在扩容上面,string增长会根据1.5倍扩容来reserve ,假如你现在是64长度的capacity,那么你要扩到80,他会给你扩到96。
综上就是,扩容全听你的,缩容不听你的。
shrink_to_fit
这个也好说,强制缩容,让capacity=size
元素操作类
operator[]和at
作用都是一样的,只是一个断言,一个抛异常。
这个同back一样,返回对应点的引用。
data
data就是返回一个同类型的数组给你。
修改类
第一个就是重新初始化,对之前的数据进行覆盖:
相对于构造函数,少了拷贝,默认和右值引用。其他和对应的构造是一样的。
push_back,emplace_back功能上是一样的,但是emplace_back在某些场景下是比push_back快的。他们都是尾插。
pop_back就是尾删
insert和emplace
insert第一个参数就是要插入的下标之前插入n个数,后面的参数和构造函数的传参为一不同的就是没有默认构造。
emplace和其实同样的功能
erase
erase有两个传参分别传开头和结尾的迭代器,如果不穿结尾迭代器默认全部删除
swap
swap相比于传统的swap来说,只是浅交换,将三个变量进行交换,因为传统的swap会创建中间变量。
clear
清除数据但是保留容量
非成员函数
逻辑运算符
swap
这里的swap是一个实例化函数,专门针对vector的,防止实例化了原版的swap。这个swap是调用vector类的swap函数。
vector的实现
有了顺序表的基础和string的基础,我们实现vector就是手拿把掐的事情: