一.vector的定义

1.vector():无参构造

创建一个空的 vector。

 里面没有任何元素。

2.vector(size_type n, const value_type& val = value_type())

构造并初始化 n 个元素

 表示创建 5 个元素,每个元素都是 10。

输出:10 10 10 10 10

如果不写第二个参数

 等价于

 再例如

 等价于创建 3 个空字符串:

 

 表示当前类型的默认值

3.vector(const vector& x):

拷贝构造

用一个已有的 vector 创建另一个新的 vector

 此时 v2 里面的数据和 v1 一样

也可以这样写

 这也是拷贝构造。

注意:v1 和 v2 是两个独立的容器。修改其中一个,不会影响另一个。

 此时:

 4.vector(InputIterator first, InputIterator last):

   迭代器区间构造

用一段区间来初始化 vector。

 表示用 v1 从 begin() 到 end() 的区间构造 v2。

结果:1 2 3 4 5

重点:区间是左闭右开。

原数据:1 2 3 4 5

构造结果:2 3 4

因为:

begin() + 1 指向 2

begin() + 4 指向 5

不包含 5

二.vector iterator 的使用

begin():获取第一个元素的位置。

end():获取最后一个元素的下一个位置。

注意:end() 不是最后一个元素,它是最后一个元素后面的位置。

 输出:1

这里 it 指向第一个元素,*it 表示取出当前位置的数据。

正向遍历

 输出:1 2 3 4 5

rbegin():获取最后一个元素的位置。

rend():获取第一个元素前一个位置。

它们用于反向遍历

 输出:5 4 3 2 1

三. vector 空间增长问题

1. size

当前数据个数

 输出:3

size() 表示:当前实际存储的数据数量

 2. capacity

当前容量大小

capacity 表示:当前底层空间最多能放多少元素

 

 已经用了 3 个位置, 但底层其实开了 8 个位置。

vector 不能每插入一个元素就重新申请空间,

效率会炸,所以 vector 会提前多申请空间,留着以后继续插入,这就是 capacity 的意义。

 

vector 扩容机制

 当插入第 5 个元素时:vector 会申请更大的空间(通常 2 倍),拷贝旧数据,释放旧空间。

3. empty

判断是否为空

 输出:  1

4. resize 

 修改元素个数 size

情况1 :变小

 结果:

 后面的元素被删除

size 和 capacity

 resize 缩小通常不会缩容。

情况2:变大

结果:

新增元素默认初始化 

指定新增值

 结果:

resize 的本质

resize 操作的是“元素数量”,不是容量。

 执行:

 结果:

 5. reserve

改变 capacity

 提前预留空间

reserve 只改 capacity,不会改 size。

 输出:0

         100

提前预留空间,不会频繁扩容,性能提升非常明显 。

四.vector 增删查改

1. push_back —— 尾插

作用:在 vector 尾部插入元素

 结果:

 vector 底层是顺序表。

尾插时:

如果空间够 → 直接放末尾

如果空间不够 → 扩容 → 拷贝旧数据 → 插入新数据

2. pop_back —— 尾删

作用:删除最后一个元素

 结果:

 注意:

pop_back():没有返回值,不能删除空 vector

错误:

 本质其实只是size --,所以效率非常高 

3. find —— 查找

find 不是 vector 成员函数

它属于:<algorithm>

使用时要包含头文件#include <algorithm>

用法:

作用:在区间中查找某个值

 如果找到的话

返回对应位置迭代器

找不到就返回end()

4. insert —— 插入

作用:在 pos 之前插入 val

 

 结果:

 中间插入

 结果:

本质

vector 是连续空间,中间插入时,后面的元素都要后移。

5. erase —— 删除

 作用:删除 pos 位置元素

 结果:

 删除区间

 删除前两个元素

erase 返回值

返回:被删除位置的下一个迭代器

因为删除后,原迭代器失效了 

 

经典错误:

 因为erase 后 it 已失效

正确写法:

 将下一个位置的迭代器再给it

6. swap —— 交换两个 vector

 作用:交换两个 vector 的数据空间

 结果:

本质:

不是逐个元素交换,而是直接交换内部指针,所以效率极高

7. operator[] —— 像数组一样访问

 作用:访问第 i 个元素

 输出: 2

 

修改元素

 结果:

 注意:[] 不检查越界。

 可能直接崩溃。

 

五.vector 迭代器失效问题。

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。

1.会引起其底层空间改变的操作,都有可能是迭代器失效

 假设:

 当前:

 现在:

空间不够,vector 会:

申请新空间,拷贝旧数据,释放旧空间

原迭代器it原本指向旧空间,但旧空间已经没了。

于是:迭代器失效

push_back,insert,resize,reserve都可能引发迭代器失效

2.指定位置元素的删除操作

删除前:

 

 vector 会后面元素整体前移

结果:

 原来指向 30 的迭代器,现在位置已经变化

所以删除位置后的迭代器失效

3. 与vector类似,string在插入+扩容操作+erase之后,迭代器也会失效

 

 现在:

 执行:

 如果空间不够string 会:

申请新空间,拷贝数据,释放旧空间

原迭代器it原本指向旧内存,但旧空间释放了

于是失效

4.解决迭代器失效的方法

在使用前,对迭代器重新赋值即可

erase

 insert / push_back / reserve / resize 可能扩容,操作后重新获取迭代器。

 提前 reserve,减少扩容导致的失效。

 reserve 只能减少扩容风险,不能解决 insert / erase 导致元素移动的问题。

最标准写法就是

 它的含义是:删除当前位置,并让 it 指向下一个有效位置。

 

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐