STL---vector

目录

一、vector的介绍及使用

官网的介绍:

介绍:

二、vector的使用

(1)vector的构造函数

1.无参构造

2.构造并初始化n个val

3.拷贝构造

4.使用一段迭代器区间进行构造

(2)vector的迭代器使用

(3)vector空间增长的问题

(4)vector的增删查改

三、vector的迭代器失效问题

对于vector迭代器可能会出现失效的几种操作:

(1)会引起底层空间的改变,都有可能使迭代器失效

(2)指定位置删除元素的操作,也可能导致迭代器失效

四、vector在oj中的使用

(1)只出现一次的数字

(2)杨辉三角


一、vector的介绍及使用

官网的介绍:

STL---vector_第1张图片

介绍:

(1)vector是表示可变大小数组的序列容器。

(2)就像数组一样,vector也采用连续的物理空间来存放数据。也就意味着vector可以像普通数组一样使用下标的随机访问,和普通数组一样高效。但是也有和数组不一样的地方,他的大小是可以动态改变的,不过这个不需要我们来改变,他的大小会由该容器的类(封装好了扩容等等的函数)自动扩容。

(3)本质上来说,vector采用动态内存管理开辟的空间来存储数据,当新数据插入的时候,这个数组会因为要增加空间而重新开辟一块空间,然后把之前的数据依次拷贝到新空间中,就时间复杂度而言,这是一个代价相当高的动作,所以vector实际中并不是每一次都要重新分配空间的,而是以二倍(不同的编译器的源代码不同,有的可能是1.5倍扩容等等)的方式扩容。

(4)vector分配空间的策略:vector会分配一些额外的空间以适应可能的增长,因为实际的存储空间应当要比实际需要的空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于一般情况下,在末尾插入一个数据的时间复杂度是常数。

(5)因此,vector占用了更多的存储空间,来获得管理存储空间的能力,并且以一种有效的方式动态增长。

(6)与其他容器(dequeue,list,forward_list等)相比,vector访问元素更加高效,而且在末尾插入和删除数据也能更加高效。但是事物都有两面性,在非末尾对数据的插入和删除会较为低效。

二、vector的使用

        在学习任何东西的时候,我们往往不是上来就研究他的底层实现原理,而是先学会用,学习vector也是如此,下面我们来看看vector的常用接口函数。

(1)vector的构造函数

STL---vector_第2张图片

STL---vector_第3张图片

        对于上面的英文描述你是不是看的眼花缭乱头晕目眩了,没关系我列出了一张图清晰的归纳了上述参考文档

STL---vector_第4张图片

1.无参构造

        首先映入眼帘的就是我们的无参构造函数,也就是我们通常所说的默认构造函数(因为源代码中已经帮我们写好了缺省值,我们不需要再传入任何东西,这里的allocator是空间分配器,我们在后续的文章中也会讲到),他是使用的最为频繁的一种构造函数。使用的时候直接像这样,把模板参数写成你想要的类型即可。

STL---vector_第5张图片

2.构造并初始化n个val

可以看到这里和上面不同的就是他有了两个形参,一个是n个元素,另外一个是每一个元素初始化成什么样子(为什么这里是const value_type& val=valur_type()而不是直接给值0?因为你不能确定vector中到底存储的是什么类型的元素,所以给的是元素的构造函数,但是我们之前又说内置类型是没有构造函数的,其实在早期的时候的确是没有给内置类型写构造函数,但是由于模板的出现,不得不让内置类型也有默认构造函数了

STL---vector_第6张图片

3.拷贝构造

        拷贝构造可以说是默认成员函数的精华之一,拷贝构造的出现,完美的解决了浅拷贝的问题,让每一个自定义类型都有属于自己空间,再也不用担心于不同对象指向相同空间的问题了。

        vector的拷贝构造也是如此

STL---vector_第7张图片

4.使用一段迭代器区间进行构造

需要注意的是:所有的迭代器都是设计成了左闭右开的模式,使用的时候记得不要越界操作

STL---vector_第8张图片

(2)vector的迭代器使用

        STL---vector_第9张图片

        在文档中,迭代器有这么多种,不过我们常用的还是begin和end这两个,(其实在vector中我们更喜欢用下标,但是为了和其他容器相匹配,还是会使用到迭代器的)。迭代器说白了,就是为了让所有容器的访问方式变得和指针类似,有的用了一个内部类去封装来达到更多效果,有的就直接是把原生指针经过typedef后得到的

STL---vector_第10张图片

STL---vector_第11张图片

STL---vector_第12张图片

使用的时候只需要注意迭代器的名字和所属的类不要写错即可像指针一样使用

(3)vector空间增长的问题

STL---vector_第13张图片

注意:

(1)capacity这个函数在不同编译器下的实现是不一样的,比如我们在vs和g++下运行会发现,vs下的容量是1.5倍增长的,而g++下是2倍增长,所以我们不要固化的认为一定是两倍增长,具体增长多少是要根据不同的需求来确定的

(2)reserve只负责开辟空间,但是resize确可以在开空间的时候给初始值,不过reserve最大的价值在于如果我们大概知道后续需要多大的空间,可以先开辟好,减少了因为不断开辟空间并且拷贝数据带来的消耗

STL---vector_第14张图片

STL---vector_第15张图片

STL---vector_第16张图片

(4)vector的增删查改

STL---vector_第17张图片

vector的接口和别的stl没有什么区别,重点的操作都仅仅是插入,删除数据,访问数据这几个。

我们直接把代码贴上来,大家有兴趣可以自己看看

STL---vector_第18张图片

        

        唯一值得一提的是swap这个接口,虽然我们在算法库中已经有了一个swap函数,但为什么在STL中都会额外再提供一个swap函数呢?因为算法库中的swap是一个自字节一个字节的浅拷贝,不说有可能出现深拷贝不匹配的问题,还会导致效率低下,所以一般的STL都会自己写一个swap函数,他只用交换几个指针就能完成交换了,而不需要像算法库中的交换所有内容

  

三、vector的迭代器失效问题

        迭代器的主要作用就是让使用者不在关心他的底层代码,而直接当做一个指针来使用,(尽管vector迭代器在某些编译器下就是原生指针换了个名字罢了)因为他对指针进行了封装。

        而所谓的迭代器失效,迭代器底层的指针所对应的空间已经被释放了,但是我们上层使用者不知道,仍然使用了一块被释放的空间的指针,这样就会造成程序崩溃的问题。

对于vector迭代器可能会出现失效的几种操作:

(1)会引起底层空间的改变,都有可能使迭代器失效

如:resize、reserve、insert、assign、push_back等

        下面我们以reserve来举例:

STL---vector_第19张图片

        这里为什么会报错呢?因为reserve给v1扩容了,而c++中的扩容都是异地扩容,但是我们的it保存的还是扩容之前的空间的地址,这样就导致了v1这个容器已经搬走了,还留下it这个迭代器在风中凌乱。所以我们解引用it是对一块已经释放的空间进行操作,导致了程序崩溃。

解决方式,在扩容后重新赋值it为新的迭代器即可

STL---vector_第20张图片

(2)指定位置删除元素的操作,也可能导致迭代器失效

        erase删除pos位置后,其后的元素都会往前挪动覆盖数据,没有导致底层空间的地址发生改变,理论上来讲迭代器应该不会失效才对啊,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,但是end位置是没有元素的,那么此时迭代器就失效了。为了防止这一现象的出现,vs这个编译器的迭代器不再是原生指针了,而是一个封装好的类,可以用来强制检查,防止我们在erase之后再来使用该迭代器,作为补偿,erase会返回erase下一个元素的迭代器。我们只需要在使用erase的时候加上一个赋值语句就能防止迭代器失效了。

下图为编译器的强制检查

STL---vector_第21张图片

        注意:在linux下,对于迭代器失效的判定并没有vs下那么极端,因为他没有对指针进行封装,也就无法强制检查。虽然代码不一定崩溃,但是运行结果肯定就不会符合我们的预期了,而且一旦删除的最后一个节点,迭代器就超出了begin()和end()的范围了,此时是一定会崩溃的

        不过虽然可以继续使用该迭代器,但是此时的逻辑已经不是我们想要的了,所以我们在使用迭代器之后一定要记得重新赋值

        与vector类似的是,String也存在迭代器失效的问题,因为String和vector同样都是采取的一段连续的物理空间来存放数据

四、vector在oj中的使用

(1)只出现一次的数字

STL---vector_第22张图片

STL---vector_第23张图片

(2)杨辉三角

STL---vector_第24张图片

你可能感兴趣的:(c++,c++,开发语言)