揭开C++ STL的神秘面纱之vector,提升编程效率的秘密武器

目录

🚀0.前言

🚈1.vector 构造函数

🚝 1.1vector构造函数​编辑

 🚝1.2vector拷贝构造函数

🚝补充:operator=

🚈2.vector类的使用

🚝 2.1迭代器

2.1.1非const迭代器

 2.2.2const迭代器

🚝2.2vector的空间函数

 2.2.1vector::size

2.2.2vector::capacity

 2.2.3empty

 2.2.4reserve

2.2.5resize

2.2.6operator[](像数组一样访问) 

🚈3.增删查改等 

 3.1push_back尾插

3.2pop_back尾删​编辑

3.3swap(交换两个vector的数据空间)

3.4insert(在position之前插入val)

3.5erase(删除position位置的数据 )

 特别补充:迭代器失效问题

​编辑

💎4.结束语


🚀0.前言

言C++之言,聊C++之识,以C++会友,共向远方。各位博友的各位你们好啊,这里是持续分享C++知识的小赵同学,今天要分享的C++知识是vector ,在这一章,小赵将会向大家聊聊C++的vector知识 。✊

我们先来看一下关于vector的介绍,也方面我们后面更好的使用它

1. vector是表示可变大小数组的序列容器。(这个很香,动态的数组)

2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是 一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。(这里vector每次使用时候都会按一定的数据量开一定的空间,当快要满时,再以一定的倍数扩充空间)

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

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

6. 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

🚈1.vector 构造函数

🚝 1.1vector构造函数

vector的构造函数的实现和string稍有不同,内部实现中带了模板,如果你要设定vector里面存储什么元素类型只需要像下面这样设计。

vector<int>a;//a里面的元素类型为int
vector<string>b;//b里面的元素类型为string
vector<char>c;//c里面的元素类型为char
vector<vector<int>>d;//d里面的元素类型为vector<int>,这也就是二维数组

 而像这样没有给任何一个元素的构造,也就是使用的默认构造函数,里面默认时没有元素的。

而除了这种默认构造的方式,我们还有几种常用的构造方式。

vector<int>a(5.1);//a里面为5个元素为1
vector<int>b(5);//b里面的元素为5个0
vector<int>c(a.begin(), a.end());//用a构造c(迭代器的方式)
string s = "abcdef";
vector<char>d(s.begin(), s.end());//用s里面的字符构造d

 以上的这几种构造方式就是我们常用的方法,当然C++11引入{}后,我们也可以用{}去构建

vector<int>e{ 1,2,3,4,5 };//和我们之前学的C的数组一样
vector<int>f={ 1,2,3,4,5 };

 🚝1.2vector拷贝构造函数

vector<int>a={ 1,2,3,4,5 };
vector<int>b(a);//用a构造b

 大家这里有了前面string的经验使用起来应该不难

除了可以这样拷贝构造还可以这样

vector<int>c = a;

 这里面可以查看一下代码的反汇编,就能看出来这个是不是我们的拷贝构造函数

 我们发现在底层用的都是拷贝构造函数,也就是我们以后用拷贝构造函数可以这样用

🚝补充:operator=

讲完了拷贝构造的=的使用就不可避免的要与我们vector里面重载的赋值=去做一个区分了。

拷贝构造的=,故名思意是给没有初始化,尚未调用过我们的构造函数,去构造对象的。而我们重载的赋值=则是将另一个类里面的值赋值到另一个里面。(就是复制过来)

 我们尝试调用了一下vector的=,发现并没有出现内存报错,说明里面的实现机制和我们的深拷贝类似。我们自己在实现这一块的时候也要主要,内存要自己去开,然后把值进行拷贝。

🚈2.vector类的使用

🚝 2.1迭代器

vector的迭代器实现类型的很多

2.1.1非const迭代器

vector的迭代器在我们熟悉的begin和end后面加上了rbegin和rend也就是反向迭代器,就是rbegin==end,rend==begin。 使用起来和begin和end差不多。

当然还有一个比较有意思的点这里的++也应该是进行了重载,类似像是--。

用下面的图片来方便大家对于反向迭代的理解。

 2.2.2const迭代器

vector的内部除了实现了反向迭代器,还实现了const的迭代器。

和我们之前在int前面加const一样,加一个const在前面这个迭代器内部的值就不能被修改了。 

这里我们试图去修改内部的值,很明显报了错误。

🚝2.2vector的空间函数

首先我们来看一下不同平台对于vector的空间扩容方案:

capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。 这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义 的。vs是PJ版本STL,g++是SGI版本STL。

 2.2.1vector::size

这个和string的一样获取元素的个数,后面遇到类似的类也是一样,后面就不说这个函数了。

 

2.2.2vector::capacity

 也是一样获取目前vector开的空间

 

                                                        2.2.3empty

判断vector里面的元素数量是否为空,如果为空则返回true,不然返回false;

                                                         2.2.4reserve

reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问 题。

2.2.5resize

resize在开空间的同时还会进行初始化(0),影响size。

2.2.6operator[](像数组一样访问) 

 vector类也重载了[],这样就可以像访问数组一样访问我们的vector类了很香。

🚈3.增删查改等 

 3.1push_back尾插

3.2pop_back尾删

3.3swap(交换两个vector的数据空间)

 这个就是交换两个数组的元素,这个接口并不常用,了解就行。

3.4insert(在position之前插入val)

vector<int>a{ 1,2,3,4,5 };
vector<int>::iterator it=a.begin()+1;
a.insert(it, 5);//迭代器

 这里要注意的是vector用的迭代器进行插入

3.5erase(删除position位置的数据 )

 特别补充:迭代器失效问题

迭代器失效问题的原因是从哪里来的呢,其实就在我们介绍vector类的时候就有伏笔。

 在我们前面的时候我们说vector在开空间的时候,它是重新分配一个数组,也就是下面这段。

本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是 一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。

 这段话其实翻译过来就是vector会重新开一个空间,然后就原本的数组元素拷贝过去。

 而我们的迭代器用的指针,而我们新开的数组是新的地址,而之前的迭代器指向的是老数组,那么这个时候我们的迭代器就会出现失效的问题。而解决办法就是获取新的迭代器。

迭代器失效图片

另外除了insert扩容的问题,还要注意erase之后迭代器如果指向最后一个位置被删除,那么可能也会出现内存错误,访问野指针的问题。

💎4.结束语

好了小赵今天的分享就到这里了,如果大家有什么不明白的地方可以在小赵的下方留言哦,同时如果小赵的博客中有什么地方不对也希望得到大家的指点,谢谢各位家人们的支持。你们的支持是小赵创作的动力,加油。

如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持小赵,如有不足还请指点,方便小赵及时改正,感谢大家支持!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的小赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值